From d5c462f5a63fbbf1f5858aceb3f7278f1cbaacaa Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 21 May 2021 14:57:03 +0200 Subject: [PATCH] Tech ENABLE_SEQUENTIAL_LIMITS -> Show sequential print clearance regions contours while dragging objects --- src/slic3r/GUI/GLCanvas3D.cpp | 168 ++++++++++++++++++++++++++++------ src/slic3r/GUI/GLCanvas3D.hpp | 8 +- src/slic3r/GUI/Plater.cpp | 4 +- 3 files changed, 148 insertions(+), 32 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2c4fc0592..c3b9becb5 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -788,8 +788,10 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas } #if ENABLE_SEQUENTIAL_LIMITS -void GLCanvas3D::SequentialPrintClearance::set(const Polygons& polygons) +void GLCanvas3D::SequentialPrintClearance::set(const Polygons& polygons, bool fill) { + m_render_fill = fill; + m_perimeter.reset(); m_fill.reset(); if (polygons.empty()) @@ -801,37 +803,38 @@ void GLCanvas3D::SequentialPrintClearance::set(const Polygons& polygons) } size_t vertices_count = 3 * triangles_count; - GLModel::InitializationData fill_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; - entity.color = { 0.3333f, 0.0f, 0.0f, 0.5f }; - entity.positions.reserve(vertices_count); - entity.normals.reserve(vertices_count); - entity.indices.reserve(vertices_count); + if (fill) { + GLModel::InitializationData fill_data; + GLModel::InitializationData::Entity entity; + entity.type = GLModel::PrimitiveType::Triangles; + entity.color = { 0.3333f, 0.0f, 0.0f, 0.5f }; + entity.positions.reserve(vertices_count); + entity.normals.reserve(vertices_count); + entity.indices.reserve(vertices_count); - ExPolygons polygons_union = union_ex(polygons); - for (const ExPolygon& poly : polygons_union) { - std::vector triangulation = triangulate_expolygon_3d(poly, false); - for (const Vec3d& v : triangulation) { - entity.positions.emplace_back(v.cast() + Vec3f(0.0f, 0.0f, 0.0125f)); // add a small positive z to avoid z-fighting - entity.normals.emplace_back(Vec3f::UnitZ()); - size_t positions_count = entity.positions.size(); - if (positions_count % 3 == 0) { - entity.indices.emplace_back(positions_count - 3); - entity.indices.emplace_back(positions_count - 2); - entity.indices.emplace_back(positions_count - 1); + ExPolygons polygons_union = union_ex(polygons); + for (const ExPolygon& poly : polygons_union) { + std::vector triangulation = triangulate_expolygon_3d(poly, false); + for (const Vec3d& v : triangulation) { + entity.positions.emplace_back(v.cast() + Vec3f(0.0f, 0.0f, 0.0125f)); // add a small positive z to avoid z-fighting + entity.normals.emplace_back(Vec3f::UnitZ()); + size_t positions_count = entity.positions.size(); + if (positions_count % 3 == 0) { + entity.indices.emplace_back(positions_count - 3); + entity.indices.emplace_back(positions_count - 2); + entity.indices.emplace_back(positions_count - 1); + } } } - } - fill_data.entities.emplace_back(entity); - m_fill.init_from(fill_data); + fill_data.entities.emplace_back(entity); + m_fill.init_from(fill_data); + } GLModel::InitializationData perimeter_data; for (const Polygon& poly : polygons) { GLModel::InitializationData::Entity ent; ent.type = GLModel::PrimitiveType::LineLoop; - ent.color = { 1.0f, 0.0f, 0.0f, 0.5f }; ent.positions.reserve(poly.points.size()); ent.indices.reserve(poly.points.size()); unsigned int id_count = 0; @@ -849,6 +852,9 @@ void GLCanvas3D::SequentialPrintClearance::set(const Polygons& polygons) void GLCanvas3D::SequentialPrintClearance::render() const { + std::array FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f }; + std::array NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f }; + GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; @@ -860,6 +866,7 @@ void GLCanvas3D::SequentialPrintClearance::render() const glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + const_cast(&m_perimeter)->set_color(-1, m_render_fill ? FILL_COLOR : NO_FILL_COLOR); m_perimeter.render(); m_fill.render(); @@ -1459,8 +1466,7 @@ void GLCanvas3D::render() _render_selection(); _render_bed(!camera.is_looking_downward(), true); #if ENABLE_SEQUENTIAL_LIMITS - if ((!m_mouse.dragging || m_mouse.drag.move_volume_idx == -1) && - m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined && + if (m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined && !m_layers_editing.is_enabled()) _render_sequential_clearance(); #endif // ENABLE_SEQUENTIAL_LIMITS @@ -2950,6 +2956,22 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.set_start_position_3D_as_invalid(); m_mouse.position = pos.cast(); +#if ENABLE_SEQUENTIAL_LIMITS + if (evt.Dragging() && current_printer_technology() == ptFFF && fff_print()->config().complete_objects) { + switch (m_gizmos.get_current_type()) + { + case GLGizmosManager::EType::Move: + case GLGizmosManager::EType::Scale: + case GLGizmosManager::EType::Rotate: + { + update_sequential_clearance(); + break; + } + default: { break; } + } + } +#endif // ENABLE_SEQUENTIAL_LIMITS + return; } @@ -3116,6 +3138,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } m_selection.translate(cur_pos - m_mouse.drag.start_position_3D); +#if ENABLE_SEQUENTIAL_LIMITS + if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) + update_sequential_clearance(); +#endif // ENABLE_SEQUENTIAL_LIMITS wxGetApp().obj_manipul()->set_dirty(); m_dirty = true; } @@ -3396,7 +3422,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type) post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); #if ENABLE_SEQUENTIAL_LIMITS - set_sequential_print_clearance(Polygons()); + set_sequential_print_clearance(Polygons(), false); #endif // ENABLE_SEQUENTIAL_LIMITS m_dirty = true; @@ -3745,6 +3771,96 @@ void GLCanvas3D::mouse_up_cleanup() m_canvas->ReleaseMouse(); } +#if ENABLE_SEQUENTIAL_LIMITS +void GLCanvas3D::update_sequential_clearance() +{ + if (current_printer_technology() != ptFFF || !fff_print()->config().complete_objects) + return; + + // collect objects and instances from volumes + struct Object + { + int id; + GLVolumePtrs volumes; + }; + std::vector objects; + + struct Instance + { + int id; + int object_id; + Transform3d transform; + }; + std::vector instances; + + for (GLVolume* v : m_volumes.volumes) { + if (v->is_modifier || v->is_wipe_tower) + continue; + + const int object_id = v->object_idx(); + const int instance_id = v->instance_idx(); + + // update instances list + auto inst_it = std::find_if(instances.begin(), instances.end(), [object_id, instance_id](const Instance& i) { return i.object_id == object_id && i.id == instance_id; }); + if (inst_it == instances.end()) { + const Instance i = { instance_id, object_id, v->get_instance_transformation().get_matrix() }; + instances.emplace_back(i); + } + + // update objects list + if (instance_id == 0) { + auto it = std::find_if(objects.begin(), objects.end(), [object_id](const Object& o) { return o.id == object_id; }); + if (it == objects.end()) + it = objects.insert(objects.end(), { object_id, GLVolumePtrs() }); + it->volumes.emplace_back(v); + } + } + + // calculates instances 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid()) + Polygons polygons; + float shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON)); + float mitter_limit = static_cast(scale_(0.1)); + for (const Object& o : objects) { + // object 2d hull + ModelObject* model_object = m_model->objects[o.id]; + ModelInstance* model_instance0 = model_object->instances.front(); + Points obj_pts; + for (GLVolume* v : o.volumes) { + const TriangleMesh& mesh = model_object->volumes[v->composite_id.volume_id]->mesh(); + Transform3d inst_trafo = Geometry::assemble_transform({ 0.0, 0.0, model_instance0->get_offset().z() }, model_instance0->get_rotation(), + model_instance0->get_scaling_factor(), model_instance0->get_mirror()); + append(obj_pts, its_convex_hull_2d_above(mesh.its, (inst_trafo * v->get_volume_transformation().get_matrix()).cast(), 0.0f).points); + } + + obj_pts = offset(Polygon(obj_pts), + // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects + // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. + shrink_factor, + jtRound, mitter_limit).front().points; + + Pointf3s obj_pts_d; + for (const Point& p : obj_pts) { + obj_pts_d.emplace_back(unscale(p.x()), unscale(p.y()), 0.0); + } + + // instances 2d hulls + for (const Instance& i : instances) { + if (i.object_id != o.id) + continue; + + Points inst_pts; + for (const Vec3d& p : obj_pts_d) { + const Vec3d i_p = i.transform * p; + inst_pts.emplace_back(scale_(i_p.x()), scale_(i_p.y())); + } + polygons.emplace_back(Geometry::convex_hull(std::move(inst_pts))); + } + } + + set_sequential_print_clearance(polygons, false); +} +#endif // ENABLE_SEQUENTIAL_LIMITS + bool GLCanvas3D::_is_shown_on_screen() const { return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 9b823eae7..9da08aecd 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -501,9 +501,10 @@ private: { GLModel m_fill; GLModel m_perimeter; + bool m_render_fill{ true }; public: - void set(const Polygons& polygons); + void set(const Polygons& polygons, bool fill); void render() const; }; @@ -752,9 +753,8 @@ public: } #if ENABLE_SEQUENTIAL_LIMITS - void set_sequential_print_clearance(const Polygons& polygons) { - m_sequential_print_clearance.set(polygons); - } + void set_sequential_print_clearance(const Polygons& polygons, bool fill) { m_sequential_print_clearance.set(polygons, fill); } + void update_sequential_clearance(); #endif // ENABLE_SEQUENTIAL_LIMITS const Print* fff_print() const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 45242c593..920cafaa3 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2939,7 +2939,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool process_validation_warning(warning); #if ENABLE_SEQUENTIAL_LIMITS if (printer_technology == ptFFF) { - view3D->get_canvas3d()->set_sequential_print_clearance(Polygons()); + view3D->get_canvas3d()->set_sequential_print_clearance(Polygons(), false); view3D->get_canvas3d()->set_as_dirty(); view3D->get_canvas3d()->request_extra_frame(); } @@ -2955,7 +2955,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool Polygons polygons; if (print->config().complete_objects) Print::sequential_print_horizontal_clearance_valid(*print, &polygons); - view3D->get_canvas3d()->set_sequential_print_clearance(polygons); + view3D->get_canvas3d()->set_sequential_print_clearance(polygons, true); } #endif // ENABLE_SEQUENTIAL_LIMITS }