diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 94496bbf7..e32f3cde7 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -60,6 +60,8 @@ #define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) // Enable replacing a missing file during reload from disk command #define ENABLE_RELOAD_FROM_DISK_REPLACE_FILE (1 && ENABLE_2_4_0_ALPHA2) +// Enable fixing the synchronization of seams with the horizontal slider in preview +#define ENABLE_FIX_SEAMS_SYNCH (1 && ENABLE_2_4_0_ALPHA2) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 9baee7eba..397e9aa03 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1500,10 +1500,18 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) m_max_bounding_box = m_paths_bounding_box; m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size()[2] * Vec3d::UnitZ()); +#if ENABLE_FIX_SEAMS_SYNCH m_sequential_view.gcode_ids.clear(); + for (size_t i = 0; i < gcode_result.moves.size(); ++i) { + const GCodeProcessor::MoveVertex& move = gcode_result.moves[i]; + if (move.type != EMoveType::Seam) + m_sequential_view.gcode_ids.push_back(move.gcode_id); + } +#else for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) { m_sequential_view.gcode_ids.push_back(move.gcode_id); } +#endif // ENABLE_FIX_SEAMS_SYNCH std::vector vertices(m_buffers.size()); std::vector indices(m_buffers.size()); @@ -1513,9 +1521,22 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) #endif // ENABLE_SEAMS_USING_MODELS std::vector options_zs; +#if ENABLE_FIX_SEAMS_SYNCH + size_t seams_count = 0; + std::vector seams_ids; +#endif // ENABLE_FIX_SEAMS_SYNCH + // toolpaths data -> extract vertices from result for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i]; +#if ENABLE_FIX_SEAMS_SYNCH + if (curr.type == EMoveType::Seam) { + ++seams_count; + seams_ids.push_back(i); + } + + size_t move_id = i - seams_count; +#endif // ENABLE_FIX_SEAMS_SYNCH // skip first vertex if (i == 0) @@ -1556,7 +1577,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { Path& last_path = t_buffer.paths.back(); if (prev.type == curr.type && last_path.matches(curr)) +#if ENABLE_FIX_SEAMS_SYNCH + last_path.add_sub_path(prev, static_cast(v_multibuffer.size()) - 1, 0, move_id - 1); +#else last_path.add_sub_path(prev, static_cast(v_multibuffer.size()) - 1, 0, i - 1); +#endif // ENABLE_FIX_SEAMS_SYNCH } } @@ -1566,12 +1591,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) { case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; } +#if ENABLE_FIX_SEAMS_SYNCH + case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, move_id); break; } +#else case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, i); break; } +#endif // ENABLE_FIX_SEAMS_SYNCH #if ENABLE_SEAMS_USING_MODELS #if ENABLE_SEAMS_USING_BATCHED_MODELS case TBuffer::ERenderPrimitiveType::InstancedModel: { +#if ENABLE_FIX_SEAMS_SYNCH + add_model_instance(curr, inst_buffer, inst_id_buffer, move_id); +#else add_model_instance(curr, inst_buffer, inst_id_buffer, i); +#endif // ENABLE_FIX_SEAMS_SYNCH #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.instances_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -1579,7 +1612,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } case TBuffer::ERenderPrimitiveType::BatchedModel: { +#if ENABLE_FIX_SEAMS_SYNCH + add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, move_id); +#else add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, i); +#endif // ENABLE_FIX_SEAMS_SYNCH #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.batched_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -1588,7 +1625,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) #else case TBuffer::ERenderPrimitiveType::Model: { +#if ENABLE_FIX_SEAMS_SYNCH + add_model_instance(curr, inst_buffer, inst_id_buffer, move_id); +#else add_model_instance(curr, inst_buffer, inst_id_buffer, i); +#endif // ENABLE_FIX_SEAMS_SYNCH #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.instances_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -1607,7 +1648,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } // smooth toolpaths corners for the given TBuffer using triangles +#if ENABLE_FIX_SEAMS_SYNCH + auto smooth_triangle_toolpaths_corners = [&gcode_result, &seams_ids](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) { +#else auto smooth_triangle_toolpaths_corners = [&gcode_result](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) { +#endif // ENABLE_FIX_SEAMS_SYNCH auto extract_position_at = [](const VertexBuffer& vertices, size_t offset) { return Vec3f(vertices[offset + 0], vertices[offset + 1], vertices[offset + 2]); }; @@ -1681,6 +1726,16 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } }; +#if ENABLE_FIX_SEAMS_SYNCH + auto extract_move_id = [&seams_ids](size_t id) { + for (int i = seams_ids.size() - 1; i >= 0; --i) { + if (seams_ids[i] < id + i + 1) + return id + (size_t)i + 1; + } + return id; + }; +#endif // ENABLE_FIX_SEAMS_SYNCH + size_t vertex_size_floats = t_buffer.vertices.vertex_size_floats(); for (const Path& path : t_buffer.paths) { // the two segments of the path sharing the current vertex may belong @@ -1691,9 +1746,16 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const float half_width = 0.5f * path.width; for (size_t j = 1; j < path_vertices_count - 1; ++j) { size_t curr_s_id = path.sub_paths.front().first.s_id + j; +#if ENABLE_FIX_SEAMS_SYNCH + size_t move_id = extract_move_id(curr_s_id); + const Vec3f& prev = gcode_result.moves[move_id - 1].position; + const Vec3f& curr = gcode_result.moves[move_id].position; + const Vec3f& next = gcode_result.moves[move_id + 1].position; +#else const Vec3f& prev = gcode_result.moves[curr_s_id - 1].position; const Vec3f& curr = gcode_result.moves[curr_s_id].position; const Vec3f& next = gcode_result.moves[curr_s_id + 1].position; +#endif // ENABLE_FIX_SEAMS_SYNCH // select the subpaths which contains the previous/next segments if (!path.sub_paths[prev_sub_path_id].contains(curr_s_id)) @@ -1760,6 +1822,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } +#if ENABLE_FIX_SEAMS_SYNCH + // dismiss, no more needed + std::vector().swap(seams_ids); +#endif // ENABLE_FIX_SEAMS_SYNCH + for (MultiVertexBuffer& v_multibuffer : vertices) { for (VertexBuffer& v_buffer : v_multibuffer) { v_buffer.shrink_to_fit(); @@ -1860,8 +1927,18 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) using VboIndexList = std::vector; std::vector vbo_indices(m_buffers.size()); +#if ENABLE_FIX_SEAMS_SYNCH + seams_count = 0; +#endif // ENABLE_FIX_SEAMS_SYNCH + for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i]; +#if ENABLE_FIX_SEAMS_SYNCH + if (curr.type == EMoveType::Seam) + ++seams_count; + + size_t move_id = i - seams_count; +#endif // ENABLE_FIX_SEAMS_SYNCH // skip first vertex if (i == 0) @@ -1912,7 +1989,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { #endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); +#if ENABLE_FIX_SEAMS_SYNCH + last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, move_id - 1); +#else last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); +#endif // ENABLE_FIX_SEAMS_SYNCH } } @@ -1937,7 +2018,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { #endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); +#if ENABLE_FIX_SEAMS_SYNCH + last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, move_id - 1); +#else last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); +#endif // ENABLE_FIX_SEAMS_SYNCH } } @@ -1946,17 +2031,29 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) switch (t_buffer.render_primitive_type) { case TBuffer::ERenderPrimitiveType::Point: { +#if ENABLE_FIX_SEAMS_SYNCH + add_indices_as_point(curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, move_id); +#else add_indices_as_point(curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, i); +#endif // ENABLE_FIX_SEAMS_SYNCH curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); break; } case TBuffer::ERenderPrimitiveType::Line: { +#if ENABLE_FIX_SEAMS_SYNCH + add_indices_as_line(prev, curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, move_id); +#else add_indices_as_line(prev, curr, t_buffer, static_cast(i_multibuffer.size()) - 1, i_buffer, i); +#endif // ENABLE_FIX_SEAMS_SYNCH curr_vertex_buffer.second += t_buffer.max_vertices_per_segment(); break; } case TBuffer::ERenderPrimitiveType::Triangle: { +#if ENABLE_FIX_SEAMS_SYNCH + add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast(i_multibuffer.size()) - 1, i_buffer, move_id); +#else add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast(i_multibuffer.size()) - 1, i_buffer, i); +#endif // ENABLE_FIX_SEAMS_SYNCH break; } #if ENABLE_SEAMS_USING_BATCHED_MODELS @@ -2051,16 +2148,34 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // layers zs / roles / extruder ids -> extract from result size_t last_travel_s_id = 0; +#if ENABLE_FIX_SEAMS_SYNCH + seams_count = 0; +#endif // ENABLE_FIX_SEAMS_SYNCH for (size_t i = 0; i < m_moves_count; ++i) { const GCodeProcessor::MoveVertex& move = gcode_result.moves[i]; +#if ENABLE_FIX_SEAMS_SYNCH + if (move.type == EMoveType::Seam) + ++seams_count; + + size_t move_id = i - seams_count; +#endif // ENABLE_FIX_SEAMS_SYNCH + if (move.type == EMoveType::Extrude) { // layers zs const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back(); const double z = static_cast(move.position.z()); if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z) +#if ENABLE_FIX_SEAMS_SYNCH + m_layers.append(z, { last_travel_s_id, move_id }); +#else m_layers.append(z, { last_travel_s_id, i }); +#endif // ENABLE_FIX_SEAMS_SYNCH else +#if ENABLE_FIX_SEAMS_SYNCH + m_layers.get_endpoints().back().last = move_id; +#else m_layers.get_endpoints().back().last = i; +#endif // ENABLE_FIX_SEAMS_SYNCH // extruder ids m_extruder_ids.emplace_back(move.extruder_id); // roles @@ -2068,10 +2183,17 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) m_roles.emplace_back(move.extrusion_role); } else if (move.type == EMoveType::Travel) { +#if ENABLE_FIX_SEAMS_SYNCH + if (move_id - last_travel_s_id > 1 && !m_layers.empty()) + m_layers.get_endpoints().back().last = move_id; + + last_travel_s_id = move_id; +#else if (i - last_travel_s_id > 1 && !m_layers.empty()) m_layers.get_endpoints().back().last = i; - + last_travel_s_id = i; +#endif // ENABLE_FIX_SEAMS_SYNCH } }