diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 01d7d6bbd5..8e7de28704 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1799,7 +1799,9 @@ public: fprintf(f_mat.f, "# G-Code Toolpaths Materials\n"); fprintf(f_mat.f, "# Generated by %s-%s based on Slic3r\n", SLIC3R_APP_NAME, SLIC3R_VERSION); - const libvgcode::Interval& visible_range = m_viewer.get_view_visible_range(); + libvgcode::Interval visible_range = m_viewer.get_view_visible_range(); + if (m_viewer.is_top_layer_only_view_range()) + visible_range[0] = m_viewer.get_view_full_range()[0]; for (size_t i = visible_range[0]; i <= visible_range[1]; ++i) { const libvgcode::PathVertex& curr = m_viewer.get_vertex_at(i); const libvgcode::PathVertex& next = m_viewer.get_vertex_at(i + 1); @@ -1809,11 +1811,11 @@ public: unsigned char flags = 0; if (curr.gcode_id == next.gcode_id) flags |= Flag_First; - if (!nextnext.is_extrusion()) + if (i + 1 == visible_range[1] || !nextnext.is_extrusion()) flags |= Flag_Last; else flags |= Flag_Internal; - export_segment(*f_geo.f, flags, curr, next, nextnext); + export_segment(*f_geo.f, flags, i, curr, next, nextnext); } export_materials(*f_mat.f); } @@ -1825,21 +1827,18 @@ private: static const unsigned char Flag_First = 0x01; static const unsigned char Flag_Last = 0x02; static const unsigned char Flag_Internal = 0x04; - unsigned char m_flags{ 0 }; static const float Cap_Rounding_Factor; - struct SegmentLocalSystem + struct SegmentLocalAxes { Vec3f forward; Vec3f right; Vec3f up; }; - SegmentLocalSystem segment_local_system(const Vec3f& v1, const Vec3f& v2) { - SegmentLocalSystem ret; - const Vec3f line = v2 - v1; - const float line_sqlen = line.squaredNorm(); - ret.forward = (line_sqlen < 1e-4) ? Vec3f::UnitX() : line.normalized(); + SegmentLocalAxes segment_local_axes(const Vec3f& v1, const Vec3f& v2) { + SegmentLocalAxes ret; + ret.forward = (v2 - v1).normalized(); ret.right = ret.forward.cross(Vec3f::UnitZ()).normalized(); ret.up = ret.right.cross(ret.forward); return ret; @@ -1851,7 +1850,7 @@ private: Vec3f normal; }; - struct VertexCrossSection + struct CrossSection { Vertex right; Vertex top; @@ -1859,8 +1858,8 @@ private: Vertex bottom; }; - VertexCrossSection cross_section(const Vec3f& v, const Vec3f& right, const Vec3f& up, float width, float height) { - VertexCrossSection ret; + CrossSection cross_section(const Vec3f& v, const Vec3f& right, const Vec3f& up, float width, float height) { + CrossSection ret; const Vec3f w_shift = 0.5f * width * right; const Vec3f h_shift = 0.5f * height * up; ret.right.position = v + w_shift; @@ -1874,7 +1873,7 @@ private: return ret; } - VertexCrossSection normal_cross_section(const Vec3f& v, const SegmentLocalSystem& axes, float width, float height) { + CrossSection normal_cross_section(const Vec3f& v, const SegmentLocalAxes& axes, float width, float height) { return cross_section(v, axes.right, axes.up, width, height); } @@ -1885,7 +1884,7 @@ private: Straight }; - VertexCrossSection corner_cross_section(const Vec3f& v, const SegmentLocalSystem& axes1, const SegmentLocalSystem& axes2, + CrossSection corner_cross_section(const Vec3f& v, const SegmentLocalAxes& axes1, const SegmentLocalAxes& axes2, float width, float height, CornerType& corner_type) { if (std::abs(std::abs(axes1.forward.dot(axes2.forward)) - 1.0f) < EPSILON) corner_type = CornerType::Straight; @@ -1897,23 +1896,23 @@ private: return cross_section(v, right, axes1.up, width, height); } - void export_segment(FILE& f, unsigned char flags, const libvgcode::PathVertex& v1, const libvgcode::PathVertex& v2, const libvgcode::PathVertex& v3) { + void export_segment(FILE& f, unsigned char flags, size_t v1_id, const libvgcode::PathVertex& v1, const libvgcode::PathVertex& v2, const libvgcode::PathVertex& v3) { const Vec3f v1_pos = libvgcode::convert(v1.position); const Vec3f v2_pos = libvgcode::convert(v2.position); const Vec3f v3_pos = libvgcode::convert(v3.position); - const SegmentLocalSystem v1_v2 = segment_local_system(v1_pos, v2_pos); - const SegmentLocalSystem v2_v3 = segment_local_system(v2_pos, v3_pos); + const SegmentLocalAxes v1_v2 = segment_local_axes(v1_pos, v2_pos); + const SegmentLocalAxes v2_v3 = segment_local_axes(v2_pos, v3_pos); // starting cap if ((flags & Flag_First) > 0) { const Vertex v0 = { v1_pos - Cap_Rounding_Factor * v1.width * v1_v2.forward, -v1_v2.forward }; - const VertexCrossSection ncs = normal_cross_section(v1_pos, v1_v2, v1.width, v1.height); + const CrossSection ncs = normal_cross_section(v1_pos, v1_v2, v1.width, v1.height); export_vertex(f, v0); // 0 export_vertex(f, ncs.right); // 1 export_vertex(f, ncs.top); // 2 export_vertex(f, ncs.left); // 3 export_vertex(f, ncs.bottom); // 4 - export_material(f, color_id(v1)); + export_material(f, color_id(v1_id)); export_triangle(f, vertex_id(0), vertex_id(1), vertex_id(2)); export_triangle(f, vertex_id(0), vertex_id(2), vertex_id(3)); export_triangle(f, vertex_id(0), vertex_id(3), vertex_id(4)); @@ -1923,13 +1922,13 @@ private: // segment body + ending cap if ((flags & Flag_Last) > 0) { const Vertex v0 = { v2_pos + Cap_Rounding_Factor * v2.width * v1_v2.forward, v1_v2.forward }; - const VertexCrossSection ncs = normal_cross_section(v2_pos, v1_v2, v2.width, v2.height); + const CrossSection ncs = normal_cross_section(v2_pos, v1_v2, v2.width, v2.height); export_vertex(f, v0); // 0 export_vertex(f, ncs.right); // 1 export_vertex(f, ncs.top); // 2 export_vertex(f, ncs.left); // 3 export_vertex(f, ncs.bottom); // 4 - export_material(f, color_id(v2)); + export_material(f, color_id(v1_id + 1)); // segment body export_triangle(f, vertex_id(-4), vertex_id(1), vertex_id(2)); export_triangle(f, vertex_id(-4), vertex_id(2), vertex_id(-3)); @@ -1948,15 +1947,15 @@ private: } else { CornerType corner_type; - const VertexCrossSection ccs = corner_cross_section(v2_pos, v1_v2, v2_v3, v2.width, v2.height, corner_type); - const VertexCrossSection ncs12 = normal_cross_section(v2_pos, v1_v2, v2.width, v2.height); - const VertexCrossSection ncs23 = normal_cross_section(v2_pos, v2_v3, v2.width, v2.height); + const CrossSection ccs = corner_cross_section(v2_pos, v1_v2, v2_v3, v2.width, v2.height, corner_type); + const CrossSection ncs12 = normal_cross_section(v2_pos, v1_v2, v2.width, v2.height); + const CrossSection ncs23 = normal_cross_section(v2_pos, v2_v3, v2.width, v2.height); if (corner_type == CornerType::Straight) { export_vertex(f, ncs12.right); // 0 export_vertex(f, ncs12.top); // 1 export_vertex(f, ncs12.left); // 2 export_vertex(f, ncs12.bottom); // 3 - export_material(f, color_id(v2)); + export_material(f, color_id(v1_id + 1)); // segment body export_triangle(f, vertex_id(-4), vertex_id(0), vertex_id(1)); export_triangle(f, vertex_id(-4), vertex_id(1), vertex_id(-3)); @@ -1975,7 +1974,7 @@ private: export_vertex(f, ncs12.top); // 3 export_vertex(f, ncs23.left); // 4 export_vertex(f, ncs12.bottom); // 5 - export_material(f, color_id(v2)); + export_material(f, color_id(v1_id + 1)); // segment body export_triangle(f, vertex_id(-4), vertex_id(2), vertex_id(3)); export_triangle(f, vertex_id(-4), vertex_id(3), vertex_id(-3)); @@ -1999,7 +1998,7 @@ private: export_vertex(f, ncs12.top); // 3 export_vertex(f, ccs.left); // 4 export_vertex(f, ncs12.bottom); // 5 - export_material(f, color_id(v2)); + export_material(f, color_id(v1_id + 1)); // segment body export_triangle(f, vertex_id(-4), vertex_id(0), vertex_id(3)); export_triangle(f, vertex_id(-4), vertex_id(3), vertex_id(-3)); @@ -2041,14 +2040,19 @@ private: fprintf(&f, "\nnewmtl material_%zu\n", ++materials_counter); fprintf(&f, "Ka 1 1 1\n"); fprintf(&f, "Kd %g %g %g\n", static_cast(color[0]) * inv_255, - static_cast(color[1]) * inv_255, - static_cast(color[2]) * inv_255); + static_cast(color[1]) * inv_255, + static_cast(color[2]) * inv_255); fprintf(&f, "Ks 0 0 0\n"); } } - size_t color_id(const libvgcode::PathVertex& v) { - const libvgcode::Color color = m_viewer.get_vertex_color(v); + size_t color_id(size_t vertex_id) { + const libvgcode::PathVertex& v = m_viewer.get_vertex_at(vertex_id); + const size_t top_layer_id = m_viewer.is_top_layer_only_view_range() ? m_viewer.get_layers_view_range()[1] : 0; + const bool color_top_layer_only = m_viewer.get_view_full_range()[1] != m_viewer.get_view_visible_range()[1]; + const libvgcode::Color color = (color_top_layer_only && v.layer_id < top_layer_id && + (!m_viewer.is_spiral_vase_mode() || vertex_id != m_viewer.get_view_enabled_range()[0])) ? + libvgcode::Dummy_Color : m_viewer.get_vertex_color(v); auto color_it = std::find_if(m_colors.begin(), m_colors.end(), [&color](const libvgcode::Color& m) { return m == color; }); if (color_it == m_colors.end()) { m_colors.emplace_back(color); diff --git a/src/slic3r/GUI/LibVGCode/include/Viewer.hpp b/src/slic3r/GUI/LibVGCode/include/Viewer.hpp index fcc8b17d93..3e899847ea 100644 --- a/src/slic3r/GUI/LibVGCode/include/Viewer.hpp +++ b/src/slic3r/GUI/LibVGCode/include/Viewer.hpp @@ -47,6 +47,8 @@ public: bool is_top_layer_only_view_range() const; void set_top_layer_only_view_range(bool top_layer_only_view_range); + bool is_spiral_vase_mode() const; + size_t get_layers_count() const; float get_layer_z(size_t layer_id) const; std::vector get_layers_zs() const; @@ -171,6 +173,7 @@ public: float get_travels_radius() const; void set_travels_radius(float radius); + float get_wipes_radius() const; void set_wipes_radius(float radius); diff --git a/src/slic3r/GUI/LibVGCode/src/Viewer.cpp b/src/slic3r/GUI/LibVGCode/src/Viewer.cpp index d545f3be33..b07f0284f9 100644 --- a/src/slic3r/GUI/LibVGCode/src/Viewer.cpp +++ b/src/slic3r/GUI/LibVGCode/src/Viewer.cpp @@ -87,6 +87,11 @@ bool Viewer::is_top_layer_only_view_range() const return m_impl->is_top_layer_only_view_range(); } +bool Viewer::is_spiral_vase_mode() const +{ + return m_impl->is_spiral_vase_mode(); +} + void Viewer::set_top_layer_only_view_range(bool top_layer_only_view_range) { m_impl->set_top_layer_only_view_range(top_layer_only_view_range); diff --git a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp index e794c2d3d4..c7d5fd221c 100644 --- a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp +++ b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp @@ -697,7 +697,7 @@ void ViewerImpl::update_colors() { update_color_ranges(); - const uint32_t top_layer_id = m_settings.top_layer_only_view_range ? m_layers.get_view_range()[1] : 0; + const size_t top_layer_id = m_settings.top_layer_only_view_range ? m_layers.get_view_range()[1] : 0; const bool color_top_layer_only = m_view_range.get_full()[1] != m_view_range.get_visible()[1]; std::vector colors(m_vertices.size()); for (size_t i = 0; i < m_vertices.size(); ++i) { diff --git a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp index d15ee37ff8..2c37fabeae 100644 --- a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp +++ b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp @@ -84,6 +84,8 @@ public: bool is_top_layer_only_view_range() const { return m_settings.top_layer_only_view_range; } void set_top_layer_only_view_range(bool top_layer_only_view_range); + bool is_spiral_vase_mode() const { return m_settings.spiral_vase_mode; } + size_t get_layers_count() const { return m_layers.count(); } float get_layer_z(size_t layer_id) const { return m_layers.get_layer_z(layer_id); } std::vector get_layers_zs() const { return m_layers.get_zs(); }