From d7dc04eb57941d04aa8757cbcd45457f49acbcf5 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 17 Apr 2018 08:18:12 +0200 Subject: [PATCH 01/11] Removed parameter filament_cooling_time (fixed value of 14s for now) --- xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 4 ++-- xs/src/libslic3r/Print.cpp | 2 -- xs/src/libslic3r/PrintConfig.cpp | 9 --------- xs/src/libslic3r/PrintConfig.hpp | 2 -- xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 1 - 6 files changed, 3 insertions(+), 17 deletions(-) diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 175de0276..c83c79a04 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -67,7 +67,7 @@ public: // Set the extruder properties. void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, - float unloading_speed, float delay, float cooling_time, std::string ramming_parameters, float nozzle_diameter) + float unloading_speed, float delay, std::string ramming_parameters, float nozzle_diameter) { //while (m_filpar.size() < idx+1) // makes sure the required element is in the vector m_filpar.push_back(FilamentParameters()); @@ -78,7 +78,7 @@ public: m_filpar[idx].loading_speed = loading_speed; m_filpar[idx].unloading_speed = unloading_speed; m_filpar[idx].delay = delay; - m_filpar[idx].cooling_time = cooling_time; + m_filpar[idx].cooling_time = 14.f; // let's fix it for now, cooling moves will be reworked for 1.41 anyway m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index c19c97fae..e692b1e9e 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -186,7 +186,6 @@ bool Print::invalidate_state_by_config_options(const std::vectorconfig.filament_loading_speed.get_at(i), this->config.filament_unloading_speed.get_at(i), this->config.filament_toolchange_delay.get_at(i), - this->config.filament_cooling_time.get_at(i), this->config.filament_ramming_parameters.get_at(i), this->config.nozzle_diameter.get_at(i)); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 1e7e0bacc..02995baf3 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -481,15 +481,6 @@ PrintConfigDef::PrintConfigDef() def->cli = "filament-toolchange-delay=f@"; def->min = 0; def->default_value = new ConfigOptionFloats { 0. }; - - def = this->add("filament_cooling_time", coFloats); - def->label = L("Cooling time"); - def->tooltip = L("The filament is slowly moved back and forth after retraction into the cooling tube " - "for this amount of time."); - def->cli = "filament_cooling_time=i@"; - def->sidetext = L("s"); - def->min = 0; - def->default_value = new ConfigOptionFloats { 14.f }; def = this->add("filament_ramming_parameters", coStrings); def->label = L("Ramming parameters"); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 967a87310..2e36ca665 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -476,7 +476,6 @@ public: ConfigOptionFloats filament_loading_speed; ConfigOptionFloats filament_unloading_speed; ConfigOptionFloats filament_toolchange_delay; - ConfigOptionFloats filament_cooling_time; ConfigOptionStrings filament_ramming_parameters; ConfigOptionBool gcode_comments; ConfigOptionEnum gcode_flavor; @@ -534,7 +533,6 @@ protected: OPT_PTR(filament_loading_speed); OPT_PTR(filament_unloading_speed); OPT_PTR(filament_toolchange_delay); - OPT_PTR(filament_cooling_time); OPT_PTR(filament_ramming_parameters); OPT_PTR(gcode_comments); OPT_PTR(gcode_flavor); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index d48c9bf8f..34b4c5326 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -209,7 +209,7 @@ const std::vector& Preset::filament_options() static std::vector s_opts { "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "extrusion_multiplier", "filament_density", "filament_cost", "filament_loading_speed", "filament_unloading_speed", "filament_toolchange_delay", - "filament_cooling_time", "filament_ramming_parameters", "temperature", "first_layer_temperature", "bed_temperature", + "filament_ramming_parameters", "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode","compatible_printers", "compatible_printers_condition", "inherits" diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index cc4b18c7c..3e4d8ce60 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -1287,7 +1287,6 @@ void TabFilament::build() optgroup->append_single_option_line("filament_loading_speed"); optgroup->append_single_option_line("filament_unloading_speed"); optgroup->append_single_option_line("filament_toolchange_delay"); - optgroup->append_single_option_line("filament_cooling_time"); line = { _(L("Ramming")), "" }; line.widget = [this](wxWindow* parent){ auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); From 3bedcf441390a12e10a3d6e1c9c94421c1dbb9e7 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 17 Apr 2018 15:04:14 +0200 Subject: [PATCH 02/11] Tweaks in generation of rendering geometry for preview toolpaths. Fixes #240 and #348 --- xs/src/slic3r/GUI/3DScene.cpp | 178 ++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 72 deletions(-) diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index aa86ae203..7f5e632bb 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -788,15 +788,14 @@ static void thick_lines_to_indexed_vertex_array( #define TOP 2 #define BOTTOM 3 - Line prev_line; // right, left, top, bottom int idx_prev[4] = { -1, -1, -1, -1 }; double bottom_z_prev = 0.; Pointf b1_prev; - Pointf b2_prev; Vectorf v_prev; int idx_initial[4] = { -1, -1, -1, -1 }; double width_initial = 0.; + double bottom_z_initial = 0.0; // loop once more in case of closed loops size_t lines_end = closed ? (lines.size() + 1) : lines.size(); @@ -804,13 +803,18 @@ static void thick_lines_to_indexed_vertex_array( size_t i = (ii == lines.size()) ? 0 : ii; const Line &line = lines[i]; double len = unscale(line.length()); + double inv_len = 1.0 / len; double bottom_z = top_z - heights[i]; - double middle_z = (top_z + bottom_z) / 2.; + double middle_z = 0.5 * (top_z + bottom_z); double width = widths[i]; - + + bool is_first = (ii == 0); + bool is_last = (ii == lines_end - 1); + bool is_closing = closed && is_last; + Vectorf v = Vectorf::new_unscale(line.vector()); - v.scale(1. / len); - + v.scale(inv_len); + Pointf a = Pointf::new_unscale(line.a); Pointf b = Pointf::new_unscale(line.b); Pointf a1 = a; @@ -818,17 +822,19 @@ static void thick_lines_to_indexed_vertex_array( Pointf b1 = b; Pointf b2 = b; { - double dist = width / 2.; // scaled - a1.translate(+dist*v.y, -dist*v.x); - a2.translate(-dist*v.y, +dist*v.x); - b1.translate(+dist*v.y, -dist*v.x); - b2.translate(-dist*v.y, +dist*v.x); + double dist = 0.5 * width; // scaled + double dx = dist * v.x; + double dy = dist * v.y; + a1.translate(+dy, -dx); + a2.translate(-dy, +dx); + b1.translate(+dy, -dx); + b2.translate(-dy, +dx); } // calculate new XY normals Vector n = line.normal(); Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x, n.y, 0); - xy_right_normal.scale(1.f / len); + xy_right_normal.scale(inv_len); int idx_a[4]; int idx_b[4]; @@ -837,14 +843,21 @@ static void thick_lines_to_indexed_vertex_array( bool bottom_z_different = bottom_z_prev != bottom_z; bottom_z_prev = bottom_z; + if (!is_first && bottom_z_different) + { + // Found a change of the layer thickness -> Add a cap at the end of the previous segment. + volume.push_quad(idx_b[BOTTOM], idx_b[LEFT], idx_b[TOP], idx_b[RIGHT]); + } + // Share top / bottom vertices if possible. - if (ii == 0) { - idx_a[TOP] = idx_last ++; + if (is_first) { + idx_a[TOP] = idx_last++; volume.push_geometry(a.x, a.y, top_z , 0., 0., 1.); } else { idx_a[TOP] = idx_prev[TOP]; } - if (ii == 0 || bottom_z_different) { + + if (is_first || bottom_z_different) { // Start of the 1st line segment or a change of the layer thickness while maintaining the print_z. idx_a[BOTTOM] = idx_last ++; volume.push_geometry(a.x, a.y, bottom_z, 0., 0., -1.); @@ -852,13 +865,15 @@ static void thick_lines_to_indexed_vertex_array( volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); idx_a[RIGHT] = idx_last ++; volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); - } else { + } + else { idx_a[BOTTOM] = idx_prev[BOTTOM]; } - if (ii == 0) { + if (is_first) { // Start of the 1st line segment. width_initial = width; + bottom_z_initial = bottom_z; memcpy(idx_initial, idx_a, sizeof(int) * 4); } else { // Continuing a previous segment. @@ -866,43 +881,54 @@ static void thick_lines_to_indexed_vertex_array( double v_dot = dot(v_prev, v); bool sharp = v_dot < 0.707; // sin(45 degrees) if (sharp) { - // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn. - idx_a[RIGHT] = idx_last ++; - volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); - idx_a[LEFT ] = idx_last ++; - volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); + if (!bottom_z_different) + { + // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn. + idx_a[RIGHT] = idx_last++; + volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); + idx_a[LEFT] = idx_last++; + volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); + } } if (v_dot > 0.9) { - // The two successive segments are nearly collinear. - idx_a[LEFT ] = idx_prev[LEFT]; - idx_a[RIGHT] = idx_prev[RIGHT]; - } else if (! sharp) { - // Create a sharp corner with an overshot and average the left / right normals. - // At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc. - Pointf intersection; - Geometry::ray_ray_intersection(b1_prev, v_prev, a1, v, intersection); - a1 = intersection; - a2 = 2. * a - intersection; - assert(length(a1.vector_to(a)) < width); - assert(length(a2.vector_to(a)) < width); - float *n_left_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6; - float *p_left_prev = n_left_prev + 3; - float *n_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6; - float *p_right_prev = n_right_prev + 3; - p_left_prev [0] = float(a2.x); - p_left_prev [1] = float(a2.y); - p_right_prev[0] = float(a1.x); - p_right_prev[1] = float(a1.y); - xy_right_normal.x += n_right_prev[0]; - xy_right_normal.y += n_right_prev[1]; - xy_right_normal.scale(1. / length(xy_right_normal)); - n_left_prev [0] = float(-xy_right_normal.x); - n_left_prev [1] = float(-xy_right_normal.y); - n_right_prev[0] = float( xy_right_normal.x); - n_right_prev[1] = float( xy_right_normal.y); - idx_a[LEFT ] = idx_prev[LEFT ]; - idx_a[RIGHT] = idx_prev[RIGHT]; - } else if (cross(v_prev, v) > 0.) { + if (!bottom_z_different) + { + // The two successive segments are nearly collinear. + idx_a[LEFT ] = idx_prev[LEFT]; + idx_a[RIGHT] = idx_prev[RIGHT]; + } + } + else if (!sharp) { + if (!bottom_z_different) + { + // Create a sharp corner with an overshot and average the left / right normals. + // At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc. + Pointf intersection; + Geometry::ray_ray_intersection(b1_prev, v_prev, a1, v, intersection); + a1 = intersection; + a2 = 2. * a - intersection; + assert(length(a1.vector_to(a)) < width); + assert(length(a2.vector_to(a)) < width); + float *n_left_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6; + float *p_left_prev = n_left_prev + 3; + float *n_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6; + float *p_right_prev = n_right_prev + 3; + p_left_prev [0] = float(a2.x); + p_left_prev [1] = float(a2.y); + p_right_prev[0] = float(a1.x); + p_right_prev[1] = float(a1.y); + xy_right_normal.x += n_right_prev[0]; + xy_right_normal.y += n_right_prev[1]; + xy_right_normal.scale(1. / length(xy_right_normal)); + n_left_prev [0] = float(-xy_right_normal.x); + n_left_prev [1] = float(-xy_right_normal.y); + n_right_prev[0] = float( xy_right_normal.x); + n_right_prev[1] = float( xy_right_normal.y); + idx_a[LEFT ] = idx_prev[LEFT ]; + idx_a[RIGHT] = idx_prev[RIGHT]; + } + } + else if (cross(v_prev, v) > 0.) { // Right turn. Fill in the right turn wedge. volume.push_triangle(idx_prev[RIGHT], idx_a [RIGHT], idx_prev[TOP] ); volume.push_triangle(idx_prev[RIGHT], idx_prev[BOTTOM], idx_a [RIGHT] ); @@ -911,18 +937,21 @@ static void thick_lines_to_indexed_vertex_array( volume.push_triangle(idx_prev[LEFT], idx_prev[TOP], idx_a [LEFT] ); volume.push_triangle(idx_prev[LEFT], idx_a [LEFT], idx_prev[BOTTOM]); } - if (ii == lines.size()) { - if (! sharp) { - // Closing a loop with smooth transition. Unify the closing left / right vertices. - memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[LEFT ] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6, sizeof(float) * 6); - memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[RIGHT] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6, sizeof(float) * 6); - volume.vertices_and_normals_interleaved.erase(volume.vertices_and_normals_interleaved.end() - 12, volume.vertices_and_normals_interleaved.end()); - // Replace the left / right vertex indices to point to the start of the loop. - for (size_t u = volume.quad_indices.size() - 16; u < volume.quad_indices.size(); ++ u) { - if (volume.quad_indices[u] == idx_prev[LEFT]) - volume.quad_indices[u] = idx_initial[LEFT]; - else if (volume.quad_indices[u] == idx_prev[RIGHT]) - volume.quad_indices[u] = idx_initial[RIGHT]; + if (is_closing) { + if (!sharp) { + if (!bottom_z_different) + { + // Closing a loop with smooth transition. Unify the closing left / right vertices. + memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[LEFT ] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6, sizeof(float) * 6); + memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[RIGHT] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6, sizeof(float) * 6); + volume.vertices_and_normals_interleaved.erase(volume.vertices_and_normals_interleaved.end() - 12, volume.vertices_and_normals_interleaved.end()); + // Replace the left / right vertex indices to point to the start of the loop. + for (size_t u = volume.quad_indices.size() - 16; u < volume.quad_indices.size(); ++ u) { + if (volume.quad_indices[u] == idx_prev[LEFT]) + volume.quad_indices[u] = idx_initial[LEFT]; + else if (volume.quad_indices[u] == idx_prev[RIGHT]) + volume.quad_indices[u] = idx_initial[RIGHT]; + } } } // This is the last iteration, only required to solve the transition. @@ -931,13 +960,14 @@ static void thick_lines_to_indexed_vertex_array( } // Only new allocate top / bottom vertices, if not closing a loop. - if (closed && ii + 1 == lines.size()) { + if (is_closing) { idx_b[TOP] = idx_initial[TOP]; } else { idx_b[TOP] = idx_last ++; volume.push_geometry(b.x, b.y, top_z , 0., 0., 1.); } - if (closed && ii + 1 == lines.size() && width == width_initial) { + + if (is_closing && (width == width_initial) && (bottom_z == bottom_z_initial)) { idx_b[BOTTOM] = idx_initial[BOTTOM]; } else { idx_b[BOTTOM] = idx_last ++; @@ -949,22 +979,26 @@ static void thick_lines_to_indexed_vertex_array( idx_b[RIGHT ] = idx_last ++; volume.push_geometry(b1.x, b1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); - prev_line = line; memcpy(idx_prev, idx_b, 4 * sizeof(int)); bottom_z_prev = bottom_z; b1_prev = b1; - b2_prev = b2; - v_prev = v; + v_prev = v; + + if (bottom_z_different) + { + // Found a change of the layer thickness -> Add a cap at the beginning of this segment. + volume.push_quad(idx_a[BOTTOM], idx_a[RIGHT], idx_a[TOP], idx_a[LEFT]); + } if (! closed) { // Terminate open paths with caps. - if (i == 0) + if (is_first && !bottom_z_different) volume.push_quad(idx_a[BOTTOM], idx_a[RIGHT], idx_a[TOP], idx_a[LEFT]); // We don't use 'else' because both cases are true if we have only one line. - if (i + 1 == lines.size()) + if (is_last && !bottom_z_different) volume.push_quad(idx_b[BOTTOM], idx_b[LEFT], idx_b[TOP], idx_b[RIGHT]); } - + // Add quads for a straight hollow tube-like segment. // bottom-right face volume.push_quad(idx_a[BOTTOM], idx_b[BOTTOM], idx_b[RIGHT], idx_a[RIGHT]); From 61ee633cd2136528ee4190b78004a9966171520c Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 17 Apr 2018 16:16:25 +0200 Subject: [PATCH 03/11] Fixed color specular component in shaders --- lib/Slic3r/GUI/3DScene.pm | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 13460cfed..75c19d89e 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1753,8 +1753,8 @@ sub _vertex_shader_Gouraud { // normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); #define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SPECULAR (0.25 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SHININESS 200.0 +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 // normalized values for (1./1.43, 0.2/1.43, 1./1.43) const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); @@ -1784,15 +1784,9 @@ varying vec3 delta_box_max; void main() { - vec3 eye = -normalize((gl_ModelViewMatrix * gl_Vertex).xyz); - // First transform the normal into camera space and normalize the result. vec3 normal = normalize(gl_NormalMatrix * gl_Normal); - // Now normalize the light's direction. Note that according to the OpenGL specification, the light is stored in eye space. - // Also since we're talking about a directional light, the position field is actually direction. - vec3 halfVector = normalize(LIGHT_TOP_DIR + eye); - // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); @@ -1801,7 +1795,7 @@ void main() intensity.y = 0.0; if (NdotL > 0.0) - intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS); + intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); @@ -1926,8 +1920,8 @@ sub _vertex_shader_variable_layer_height { const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); #define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SPECULAR (0.25 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SHININESS 200.0 +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) @@ -1943,15 +1937,9 @@ varying float object_z; void main() { - vec3 eye = -normalize((gl_ModelViewMatrix * gl_Vertex).xyz); - // First transform the normal into camera space and normalize the result. vec3 normal = normalize(gl_NormalMatrix * gl_Normal); - // Now normalize the light's direction. Note that according to the OpenGL specification, the light is stored in eye space. - // Also since we're talking about a directional light, the position field is actually direction. - vec3 halfVector = normalize(LIGHT_TOP_DIR + eye); - // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); @@ -1960,7 +1948,7 @@ void main() intensity.y = 0.0; if (NdotL > 0.0) - intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS); + intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(normal, reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular) NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); From 2ef164eeef2d72326469c115e4135c10bd94be1e Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 18 Apr 2018 09:44:49 +0200 Subject: [PATCH 04/11] Fixed cut contours in cut dialog 3D view --- lib/Slic3r/GUI/3DScene.pm | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 75c19d89e..da04747c5 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1330,8 +1330,8 @@ sub Render { glEnable(GL_CULL_FACE) if ($self->enable_picking); } - # draw cutting plane if (defined $self->cutting_plane_z) { + # draw cutting plane my $plane_z = $self->cutting_plane_z; my $bb = $volumes_bb; glDisable(GL_CULL_FACE); @@ -1347,6 +1347,15 @@ sub Render { glEnd(); glEnable(GL_CULL_FACE); glDisable(GL_BLEND); + + # draw cutting contours + glEnableClientState(GL_VERTEX_ARRAY); + glLineWidth(2); + glColor3f(0, 0, 0); + glVertexPointer_c(3, GL_FLOAT, 0, $self->cut_lines_vertices->ptr()); + glDrawArrays(GL_LINES, 0, $self->cut_lines_vertices->elements / 3); + glVertexPointer_c(3, GL_FLOAT, 0, 0); + glDisableClientState(GL_VERTEX_ARRAY); } # draw warning message @@ -1393,18 +1402,10 @@ sub draw_volumes { $volume->render; } glDisableClientState(GL_NORMAL_ARRAY); - glDisable(GL_BLEND); - - glEnable(GL_CULL_FACE); - - if (defined $self->cutting_plane_z) { - glLineWidth(2); - glColor3f(0, 0, 0); - glVertexPointer_c(3, GL_FLOAT, 0, $self->cut_lines_vertices->ptr()); - glDrawArrays(GL_LINES, 0, $self->cut_lines_vertices->elements / 3); - glVertexPointer_c(3, GL_FLOAT, 0, 0); - } glDisableClientState(GL_VERTEX_ARRAY); + + glDisable(GL_BLEND); + glEnable(GL_CULL_FACE); } sub mark_volumes_for_layer_height { From c9e4c831c2c4f53b0e53f97493d1d77aca592f36 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 18 Apr 2018 10:17:22 +0200 Subject: [PATCH 05/11] Axes with fixed size in 3D previews --- lib/Slic3r/GUI/3DScene.pm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index da04747c5..d8af6f71c 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1281,10 +1281,7 @@ sub Render { # disable depth testing so that axes are not covered by ground glDisable(GL_DEPTH_TEST); my $origin = $self->origin; - my $axis_len = max( - 0.3 * max(@{ $self->bed_bounding_box->size }), - 2 * max(@{ $volumes_bb->size }), - ); + my $axis_len = $self->use_plain_shader ? 0.3 * max(@{ $self->bed_bounding_box->size }) : 2 * max(@{ $volumes_bb->size }); glLineWidth(2); glBegin(GL_LINES); # draw line for x axis From 8ab62d702c4a97579a7afbb455982c4d006ac911 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 18 Apr 2018 18:06:07 +0200 Subject: [PATCH 06/11] Fixed memory leak of TabIface. Added documentation of the XS interface on how the Ref<> and Clone<> wrappers work. --- xs/src/xsinit.h | 26 ++++++++++++++++++++++++-- xs/xsp/GUI.xsp | 2 +- xs/xsp/typemap.xspt | 1 - 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h index 96c4b74d7..9cb60384f 100644 --- a/xs/src/xsinit.h +++ b/xs/src/xsinit.h @@ -85,8 +85,12 @@ namespace Slic3r { template struct ClassTraits { + // Name of a Perl alias of a C++ class type, owned by Perl, reference counted. static const char* name; - static const char* name_ref; + // Name of a Perl alias of a C++ class type, owned by the C++ code. + // The references shall be enumerated at the end of XS.pm, where the desctructor is undefined with sub DESTROY {}, + // so Perl will never delete the object instance. + static const char* name_ref; }; // use this for typedefs for which the forward prototype @@ -99,11 +103,16 @@ struct ClassTraits { class cname; \ __REGISTER_CLASS(cname, perlname); +// Return Perl alias to a C++ class name. template const char* perl_class_name(const T*) { return ClassTraits::name; } +// Return Perl alias to a C++ class name, suffixed with ::Ref. +// Such a C++ class instance will not be destroyed by Perl, the instance destruction is left to the C++ code. template const char* perl_class_name_ref(const T*) { return ClassTraits::name_ref; } +// Mark the Perl SV (Scalar Value) as owning a "blessed" pointer to an object reference. +// Perl will never release the C++ instance. template SV* perl_to_SV_ref(T &t) { SV* sv = newSV(0); @@ -111,6 +120,8 @@ SV* perl_to_SV_ref(T &t) { return sv; } +// Mark the Perl SV (Scalar Value) as owning a "blessed" pointer to an object instance. +// Perl will own the C++ instance, therefore it will also release it. template SV* perl_to_SV_clone_ref(const T &t) { SV* sv = newSV(0); @@ -118,6 +129,8 @@ SV* perl_to_SV_clone_ref(const T &t) { return sv; } +// Reference wrapper to provide a C++ instance to Perl while keeping Perl from destroying the instance. +// The instance is created temporarily by XS.cpp just to provide Perl with a CLASS name and a object instance pointer. template class Ref { T* val; @@ -125,10 +138,15 @@ public: Ref() : val(NULL) {} Ref(T* t) : val(t) {} Ref(const T* t) : val(const_cast(t)) {} + // Called by XS.cpp to convert the referenced object instance to a Perl SV, before it is blessed with the name + // returned by CLASS() operator T*() const { return val; } + // Name to bless the Perl SV with. The name ends with a "::Ref" suffix to keep Perl from destroying the object instance. static const char* CLASS() { return ClassTraits::name_ref; } }; - + +// Wrapper to clone a C++ object instance before passing it to Perl for ownership. +// This wrapper instance is created temporarily by XS.cpp to provide Perl with a CLASS name and a object instance pointer. template class Clone { T* val; @@ -136,7 +154,11 @@ public: Clone() : val(NULL) {} Clone(T* t) : val(new T(*t)) {} Clone(const T& t) : val(new T(t)) {} + // Called by XS.cpp to convert the cloned object instance to a Perl SV, before it is blessed with the name + // returned by CLASS() operator T*() const { return val; } + // Name to bless the Perl SV with. If there is a destructor registered in the XSP file for this class, then Perl will + // call this destructor when the reference counter of this SV drops to zero. static const char* CLASS() { return ClassTraits::name; } }; diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index 1376ff164..406d71828 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -39,7 +39,7 @@ void add_debug_menu(SV *ui, int event_language_change) void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed) %code%{ Slic3r::GUI::create_preset_tabs(no_controller, event_value_change, event_presets_changed); %}; -Ref get_preset_tab(char *name) +TabIface* get_preset_tab(char *name) %code%{ RETVAL=Slic3r::GUI::get_preset_tab_iface(name); %}; bool load_language() diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 0214a158d..797f3c19f 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -211,7 +211,6 @@ %typemap{PresetHints*}; %typemap{Ref}{simple}; %typemap{TabIface*}; -%typemap{Ref}{simple}; %typemap{PrintRegionPtrs*}; %typemap{PrintObjectPtrs*}; From d1580f67dfd21420e2b813dba4b682602f0c8973 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 18 Apr 2018 18:57:34 +0200 Subject: [PATCH 07/11] Fix of the previous commit. Once the Slic3r::GUI::Tab was rewritten from Ref to TabIface*, Perl takes ownership and the Tab is being incorrectly deleted by the background threads. --- lib/Slic3r.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index e55e24a7a..5e91f56ce 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -162,6 +162,7 @@ sub thread_cleanup { *Slic3r::TriangleMesh::DESTROY = sub {}; *Slic3r::GUI::AppConfig::DESTROY = sub {}; *Slic3r::GUI::PresetBundle::DESTROY = sub {}; + *Slic3r::GUI::Tab::DESTROY = sub {}; return undef; # this prevents a "Scalars leaked" warning } From ad4cd058505ae33ce7e0b23fc513384f2de44805 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 19 Apr 2018 13:31:50 +0200 Subject: [PATCH 08/11] Fixed hovering while panning/rotating camera --- lib/Slic3r/GUI/3DScene.pm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index d8af6f71c..65abf850e 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -70,6 +70,7 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init _legend_enabled _warning_enabled _apply_zoom_to_volumes_filter + _mouse_dragging ) ); @@ -146,6 +147,7 @@ sub new { $self->_warning_enabled(0); $self->use_plain_shader(0); $self->_apply_zoom_to_volumes_filter(0); + $self->_mouse_dragging(0); # Collection of GLVolume objects $self->volumes(Slic3r::GUI::_3DScene::GLVolume::Collection->new); @@ -381,6 +383,8 @@ sub mouse_event { my $pos = Slic3r::Pointf->new($e->GetPositionXY); my $object_idx_selected = $self->{layer_height_edit_last_object_id} = ($self->layer_editing_enabled && $self->{print}) ? $self->_first_selected_object_id_for_variable_layer_height_editing : -1; + $self->_mouse_dragging($e->Dragging); + if ($e->Entering && &Wx::wxMSW) { # wxMSW needs focus in order to catch mouse wheel events $self->SetFocus; @@ -1182,7 +1186,7 @@ sub Render { # Head light glLightfv_p(GL_LIGHT1, GL_POSITION, 1, 0, 1, 0); - if ($self->enable_picking) { + if ($self->enable_picking && !$self->_mouse_dragging) { if (my $pos = $self->_mouse_pos) { # Render the object for picking. # FIXME This cannot possibly work in a multi-sampled context as the color gets mangled by the anti-aliasing. From f8b1dc550685a8ca76c4d7a810151eabf08db2c1 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 23 Apr 2018 08:44:24 +0200 Subject: [PATCH 09/11] Tweaks to zooming logic --- lib/Slic3r/GUI/3DScene.pm | 124 ++++++++++++++++++++++++----- lib/Slic3r/GUI/Plater.pm | 1 + lib/Slic3r/GUI/Plater/3DPreview.pm | 21 +---- 3 files changed, 105 insertions(+), 41 deletions(-) diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 65abf850e..ff6d73399 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -201,6 +201,10 @@ sub new { $self->select_view('left'); } elsif ($key == ord('6')) { $self->select_view('right'); + } elsif ($key == ord('z')) { + $self->zoom_to_volumes; + } elsif ($key == ord('b')) { + $self->zoom_to_bed; } else { $event->Skip; } @@ -599,22 +603,23 @@ sub mouse_wheel_event { $zoom = $zoom_min if defined $zoom_min && $zoom < $zoom_min; $self->_zoom($zoom); - # In order to zoom around the mouse point we need to translate - # the camera target - my $size = Slic3r::Pointf->new($self->GetSizeWH); - my $pos = Slic3r::Pointf->new($e->GetX, $size->y - $e->GetY); #- - $self->_camera_target->translate( - # ($pos - $size/2) represents the vector from the viewport center - # to the mouse point. By multiplying it by $zoom we get the new, - # transformed, length of such vector. - # Since we want that point to stay fixed, we move our camera target - # in the opposite direction by the delta of the length of such vector - # ($zoom - 1). We then scale everything by 1/$self->_zoom since - # $self->_camera_target is expressed in terms of model units. - -($pos->x - $size->x/2) * ($zoom) / $self->_zoom, - -($pos->y - $size->y/2) * ($zoom) / $self->_zoom, - 0, - ) if 0; +# # In order to zoom around the mouse point we need to translate +# # the camera target +# my $size = Slic3r::Pointf->new($self->GetSizeWH); +# my $pos = Slic3r::Pointf->new($e->GetX, $size->y - $e->GetY); #- +# $self->_camera_target->translate( +# # ($pos - $size/2) represents the vector from the viewport center +# # to the mouse point. By multiplying it by $zoom we get the new, +# # transformed, length of such vector. +# # Since we want that point to stay fixed, we move our camera target +# # in the opposite direction by the delta of the length of such vector +# # ($zoom - 1). We then scale everything by 1/$self->_zoom since +# # $self->_camera_target is expressed in terms of model units. +# -($pos->x - $size->x/2) * ($zoom) / $self->_zoom, +# -($pos->y - $size->y/2) * ($zoom) / $self->_zoom, +# 0, +# ) if 0; + $self->on_viewport_changed->() if $self->on_viewport_changed; $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; $self->Refresh; @@ -683,9 +688,82 @@ sub select_view { sub get_zoom_to_bounding_box_factor { my ($self, $bb) = @_; - return undef if ($bb->empty); - my $max_size = max(@{$bb->size}) * 2; - return ($max_size == 0) ? undef : min($self->GetSizeWH) / $max_size; + my $max_bb_size = max(@{ $bb->size }); + return undef if ($max_bb_size == 0); + + # project the bbox vertices on a plane perpendicular to the camera forward axis + # then calculates the vertices coordinate on this plane along the camera xy axes + + # we need the view matrix, we let opengl calculate it (same as done in render sub) + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (!TURNTABLE_MODE) { + # Shift the perspective camera. + my $camera_pos = Slic3r::Pointf3->new(0,0,-$self->_camera_distance); + glTranslatef(@$camera_pos); + } + + if (TURNTABLE_MODE) { + # Turntable mode is enabled by default. + glRotatef(-$self->_stheta, 1, 0, 0); # pitch + glRotatef($self->_sphi, 0, 0, 1); # yaw + } else { + # Shift the perspective camera. + my $camera_pos = Slic3r::Pointf3->new(0,0,-$self->_camera_distance); + glTranslatef(@$camera_pos); + my @rotmat = quat_to_rotmatrix($self->quat); + glMultMatrixd_p(@rotmat[0..15]); + } + glTranslatef(@{ $self->_camera_target->negative }); + + # get the view matrix back from opengl + my @matrix = glGetFloatv_p(GL_MODELVIEW_MATRIX); + + # camera axes + my $right = Slic3r::Pointf3->new($matrix[0], $matrix[4], $matrix[8]); + my $up = Slic3r::Pointf3->new($matrix[1], $matrix[5], $matrix[9]); + my $forward = Slic3r::Pointf3->new($matrix[2], $matrix[6], $matrix[10]); + + my $bb_min = $bb->min_point(); + my $bb_max = $bb->max_point(); + my $bb_center = $bb->center(); + + # bbox vertices in world space + my @vertices = (); + push(@vertices, $bb_min); + push(@vertices, Slic3r::Pointf3->new($bb_max->x(), $bb_min->y(), $bb_min->z())); + push(@vertices, Slic3r::Pointf3->new($bb_max->x(), $bb_max->y(), $bb_min->z())); + push(@vertices, Slic3r::Pointf3->new($bb_min->x(), $bb_max->y(), $bb_min->z())); + push(@vertices, Slic3r::Pointf3->new($bb_min->x(), $bb_min->y(), $bb_max->z())); + push(@vertices, Slic3r::Pointf3->new($bb_max->x(), $bb_min->y(), $bb_max->z())); + push(@vertices, $bb_max); + push(@vertices, Slic3r::Pointf3->new($bb_min->x(), $bb_max->y(), $bb_max->z())); + + my $max_x = 0.0; + my $max_y = 0.0; + + # margin factor to give some empty space around the bbox + my $margin_factor = 1.25; + + foreach my $v (@vertices) { + # project vertex on the plane perpendicular to camera forward axis + my $pos = Slic3r::Pointf3->new($v->x() - $bb_center->x(), $v->y() - $bb_center->y(), $v->z() - $bb_center->z()); + my $proj_on_normal = $pos->x() * $forward->x() + $pos->y() * $forward->y() + $pos->z() * $forward->z(); + my $proj_on_plane = Slic3r::Pointf3->new($pos->x() - $proj_on_normal * $forward->x(), $pos->y() - $proj_on_normal * $forward->y(), $pos->z() - $proj_on_normal * $forward->z()); + + # calculates vertex coordinate along camera xy axes + my $x_on_plane = $proj_on_plane->x() * $right->x() + $proj_on_plane->y() * $right->y() + $proj_on_plane->z() * $right->z(); + my $y_on_plane = $proj_on_plane->x() * $up->x() + $proj_on_plane->y() * $up->y() + $proj_on_plane->z() * $up->z(); + + $max_x = max($max_x, $margin_factor * 2 * abs($x_on_plane)); + $max_y = max($max_y, $margin_factor * 2 * abs($y_on_plane)); + } + + my ($cw, $ch) = $self->GetSizeWH; + my $min_ratio = min($cw / $max_x, $ch / $max_y); + + return $min_ratio; } sub zoom_to_bounding_box { @@ -697,6 +775,8 @@ sub zoom_to_bounding_box { # center view around bounding box center $self->_camera_target($bb->center); $self->on_viewport_changed->() if $self->on_viewport_changed; + $self->Resize($self->GetSizeWH) if $self->IsShownOnScreen; + $self->Refresh; } } @@ -1031,8 +1111,8 @@ sub Resize { #FIXME setting the size of the box 10x larger than necessary # is only a workaround for an incorrectly set camera. # This workaround harms Z-buffer accuracy! -# my $depth = 1.05 * $self->max_bounding_box->radius(); - my $depth = 10.0 * $self->max_bounding_box->radius(); +# my $depth = 1.05 * $self->max_bounding_box->radius(); + my $depth = max(@{ $self->max_bounding_box->size }); glOrtho( -$x/2, $x/2, -$y/2, $y/2, -$depth, $depth, @@ -1162,7 +1242,7 @@ sub Render { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - { + if (!TURNTABLE_MODE) { # Shift the perspective camera. my $camera_pos = Slic3r::Pointf3->new(0,0,-$self->_camera_distance); glTranslatef(@$camera_pos); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index d59865491..5a29ab394 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1856,6 +1856,7 @@ sub object_cut_dialog { $self->remove($obj_idx); $self->load_model_objects(grep defined($_), @new_objects); $self->arrange; + $self->{canvas3D}->zoom_to_volumes if $self->{canvas3D}; } } diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index 537cb0c8f..bd49bedb6 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -10,7 +10,7 @@ use base qw(Wx::Panel Class::Accessor); use Wx::Locale gettext => 'L'; -__PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer auto_zoom)); +__PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer)); sub new { my $class = shift; @@ -21,7 +21,6 @@ sub new { $self->{number_extruders} = 1; # Show by feature type by default. $self->{preferred_color_mode} = 'feature'; - $self->auto_zoom(1); # init GUI elements my $canvas = Slic3r::GUI::3DScene->new($self); @@ -207,41 +206,29 @@ sub new { my $selection = $choice_view_type->GetCurrentSelection(); $self->{preferred_color_mode} = ($selection == 4) ? 'tool' : 'feature'; $self->gcode_preview_data->set_type($selection); - $self->auto_zoom(0); $self->reload_print; - $self->auto_zoom(1); }); EVT_CHECKLISTBOX($self, $combochecklist_features, sub { my $flags = Slic3r::GUI::combochecklist_get_flags($combochecklist_features); $self->gcode_preview_data->set_extrusion_flags($flags); - $self->auto_zoom(0); $self->refresh_print; - $self->auto_zoom(1); }); EVT_CHECKBOX($self, $checkbox_travel, sub { $self->gcode_preview_data->set_travel_visible($checkbox_travel->IsChecked()); - $self->auto_zoom(0); $self->refresh_print; - $self->auto_zoom(1); }); EVT_CHECKBOX($self, $checkbox_retractions, sub { $self->gcode_preview_data->set_retractions_visible($checkbox_retractions->IsChecked()); - $self->auto_zoom(0); $self->refresh_print; - $self->auto_zoom(1); }); EVT_CHECKBOX($self, $checkbox_unretractions, sub { $self->gcode_preview_data->set_unretractions_visible($checkbox_unretractions->IsChecked()); - $self->auto_zoom(0); $self->refresh_print; - $self->auto_zoom(1); }); EVT_CHECKBOX($self, $checkbox_shells, sub { $self->gcode_preview_data->set_shells_visible($checkbox_shells->IsChecked()); - $self->auto_zoom(0); $self->refresh_print; - $self->auto_zoom(1); }); $self->SetSizer($main_sizer); @@ -374,7 +361,7 @@ sub load_print { } $self->show_hide_ui_elements('simple'); } else { - $self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0) && $self->auto_zoom; + $self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0); $self->canvas->load_gcode_preview($self->print, $self->gcode_preview_data, \@colors); $self->show_hide_ui_elements('full'); @@ -384,10 +371,6 @@ sub load_print { } $self->update_sliders($n_layers); - - if ($self->auto_zoom) { - $self->canvas->zoom_to_volumes; - } $self->_loaded(1); } } From a3c3eb5d2af4a9e6e809377f78e3d211a2f00182 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 23 Apr 2018 15:30:41 +0200 Subject: [PATCH 10/11] Fixed GCode Preview not invalidated when deleting an object --- lib/Slic3r/GUI/Plater.pm | 1 + lib/Slic3r/GUI/Plater/3DPreview.pm | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 5a29ab394..ce78eab8e 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1677,6 +1677,7 @@ sub update { $self->{canvas}->reload_scene if $self->{canvas}; $self->{canvas3D}->reload_scene if $self->{canvas3D}; + $self->{preview3D}->reset_gcode_preview_data if $self->{preview3D}; $self->{preview3D}->reload_print if $self->{preview3D}; } diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index bd49bedb6..4834f7aed 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -289,6 +289,12 @@ sub refresh_print { $self->load_print; } +sub reset_gcode_preview_data { + my ($self) = @_; + $self->gcode_preview_data->reset; + $self->canvas->reset_legend_texture(); +} + sub load_print { my ($self) = @_; From ccd1c01d0b46354af7fe2a11a205ceee9f6c5a74 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 24 Apr 2018 14:21:31 +0200 Subject: [PATCH 11/11] Fixed automatic view type selection when changing printer --- lib/Slic3r/GUI/Plater/3DPreview.pm | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index 4834f7aed..9d8b82242 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -72,6 +72,9 @@ sub new { $choice_view_type->Append(L("Tool")); $choice_view_type->SetSelection(0); + # the following value needs to be changed if new items are added into $choice_view_type before "Tool" + $self->{tool_idx} = 5; + my $label_show_features = $self->{label_show_features} = Wx::StaticText->new($self, -1, L("Show")); my $combochecklist_features = $self->{combochecklist_features} = Wx::ComboCtrl->new(); @@ -204,7 +207,7 @@ sub new { }); EVT_CHOICE($self, $choice_view_type, sub { my $selection = $choice_view_type->GetCurrentSelection(); - $self->{preferred_color_mode} = ($selection == 4) ? 'tool' : 'feature'; + $self->{preferred_color_mode} = ($selection == $self->{tool_idx}) ? 'tool' : 'feature'; $self->gcode_preview_data->set_type($selection); $self->reload_print; }); @@ -334,7 +337,7 @@ sub load_print { # It is left to Slic3r to decide whether the print shall be colored by the tool or by the feature. # Color by feature if it is a single extruder print. my $extruders = $self->{print}->extruders; - my $type = (scalar(@{$extruders}) > 1) ? 4 : 0; + my $type = (scalar(@{$extruders}) > 1) ? $self->{tool_idx} : 0; $self->gcode_preview_data->set_type($type); $self->{choice_view_type}->SetSelection($type); # If the ->SetSelection changed the following line, revert it to "decide yourself". @@ -343,7 +346,7 @@ sub load_print { # Collect colors per extruder. my @colors = (); - if (! $self->gcode_preview_data->empty() || $self->gcode_preview_data->type == 4) { + if (! $self->gcode_preview_data->empty() || $self->gcode_preview_data->type == $self->{tool_idx}) { my @extruder_colors = @{$self->{config}->extruder_colour}; my @filament_colors = @{$self->{config}->filament_colour}; for (my $i = 0; $i <= $#extruder_colors; $i += 1) { @@ -464,11 +467,11 @@ sub set_number_extruders { if ($self->{number_extruders} != $number_extruders) { $self->{number_extruders} = $number_extruders; my $type = ($number_extruders > 1) ? - 4 # color by a tool number + $self->{tool_idx} # color by a tool number : 0; # color by a feature type $self->{choice_view_type}->SetSelection($type); $self->gcode_preview_data->set_type($type); - $self->{preferred_color_mode} = ($type == 4) ? 'tool_or_feature' : 'feature'; + $self->{preferred_color_mode} = ($type == $self->{tool_idx}) ? 'tool_or_feature' : 'feature'; } }