diff --git a/resources/profiles/Creality/SERMOONV1PRO_thumbnail.png b/resources/profiles/Creality/SERMOONV1PRO_thumbnail.png new file mode 100644 index 000000000..adbd42162 Binary files /dev/null and b/resources/profiles/Creality/SERMOONV1PRO_thumbnail.png differ diff --git a/src/PrusaSlicer_app_msvc.cpp b/src/PrusaSlicer_app_msvc.cpp index 83f24c307..90bd2d89f 100644 --- a/src/PrusaSlicer_app_msvc.cpp +++ b/src/PrusaSlicer_app_msvc.cpp @@ -242,13 +242,14 @@ int wmain(int argc, wchar_t **argv) #ifdef SLIC3R_GUI // Here one may push some additional parameters based on the wrapper type. bool force_mesa = false; + bool force_hw = false; #endif /* SLIC3R_GUI */ for (int i = 1; i < argc; ++ i) { #ifdef SLIC3R_GUI if (wcscmp(argv[i], L"--sw-renderer") == 0) force_mesa = true; else if (wcscmp(argv[i], L"--no-sw-renderer") == 0) - force_mesa = false; + force_hw = true; #endif /* SLIC3R_GUI */ argv_extended.emplace_back(argv[i]); } @@ -261,7 +262,7 @@ int wmain(int argc, wchar_t **argv) force_mesa || // Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context. // In that case, use Mesa. - ::GetSystemMetrics(SM_REMOTESESSION) || + (::GetSystemMetrics(SM_REMOTESESSION) && !force_hw) || // Try to load the default OpenGL driver and test its context version. ! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0); #endif /* SLIC3R_GUI */ diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index a6aecd205..e200b7edb 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -425,24 +425,11 @@ template<> std::function AutoArranger::get_objfn() { auto bincenter = m_bin.center(); return [this, bincenter](const Item &item) { - + auto result = objfunc(item, bincenter); - + double score = std::get<0>(result); - - auto isBig = [this](const Item& itm) { - return itm.area() / m_bin_area > BIG_ITEM_TRESHOLD ; - }; - - if(isBig(item)) { - auto mp = m_merged_pile; - mp.push_back(item.transformedShape()); - auto chull = sl::convexHull(mp); - double miss = Placer::overfit(chull, m_bin); - if(miss < 0) miss = 0; - score += miss*miss; - } - + return score; }; } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 0ab4f166b..41f4cf060 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -714,13 +714,14 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_position = volume->get_instance_offset(); m_new_scale_label_string = L("Scale"); m_new_scale = Vec3d(100.0, 100.0, 100.0); + m_new_size = selection.get_bounding_box_in_current_reference_system().first.size(); #else if (m_world_coordinates) { m_new_scale = m_new_size.cwiseQuotient(selection.get_unscaled_instance_bounding_box().size()) * 100.0; + m_new_size = selection.get_scaled_instance_bounding_box().size(); #endif // ENABLE_WORLD_COORDINATE m_new_rotate_label_string = L("Rotate"); m_new_rotation = Vec3d::Zero(); - m_new_size = selection.get_scaled_instance_bounding_box().size(); } else { #if ENABLE_WORLD_COORDINATE @@ -729,11 +730,12 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_position = Vec3d::Zero(); m_new_rotation = Vec3d::Zero(); m_new_scale = Vec3d(100.0, 100.0, 100.0); + m_new_size = selection.get_bounding_box_in_current_reference_system().first.size(); #else m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI); + m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); #endif // ENABLE_WORLD_COORDINATE m_new_scale = volume->get_instance_scaling_factor() * 100.0; - m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); } m_new_enabled = true; @@ -743,7 +745,11 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_position = box.center(); m_new_rotation = Vec3d::Zero(); m_new_scale = Vec3d(100.0, 100.0, 100.0); - m_new_size = box.size(); +#if ENABLE_WORLD_COORDINATE + m_new_size = selection.get_bounding_box_in_current_reference_system().first.size(); +#else + m_new_size = box.size(); +#endif // ENABLE_WORLD_COORDINATE m_new_rotate_label_string = L("Rotate"); m_new_scale_label_string = L("Scale"); m_new_enabled = true; @@ -766,7 +772,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_scale_label_string = L("Scale"); m_new_scale = Vec3d(100.0, 100.0, 100.0); m_new_rotation = Vec3d::Zero(); - m_new_size = volume->transformed_convex_hull_bounding_box(trafo.get_matrix()).size(); + m_new_size = selection.get_bounding_box_in_current_reference_system().first.size(); } else if (is_local_coordinates()) { m_new_move_label_string = L("Translate"); @@ -774,7 +780,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_position = Vec3d::Zero(); m_new_rotation = Vec3d::Zero(); m_new_scale = volume->get_volume_scaling_factor() * 100.0; - m_new_size = volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size()); + m_new_size = selection.get_bounding_box_in_current_reference_system().first.size(); } else { #endif // ENABLE_WORLD_COORDINATE @@ -783,8 +789,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_rotation = Vec3d::Zero(); #if ENABLE_WORLD_COORDINATE m_new_scale_label_string = L("Scale"); - m_new_size = volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix()).size(); m_new_scale = Vec3d(100.0, 100.0, 100.0); + m_new_size = selection.get_bounding_box_in_current_reference_system().first.size(); } #else m_new_scale = volume->get_volume_scaling_factor() * 100.0; @@ -797,7 +803,11 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_move_label_string = L("Translate"); m_new_rotate_label_string = L("Rotate"); m_new_scale_label_string = L("Scale"); +#if ENABLE_WORLD_COORDINATE + m_new_size = selection.get_bounding_box_in_current_reference_system().first.size(); +#else m_new_size = selection.get_bounding_box().size(); +#endif // ENABLE_WORLD_COORDINATE m_new_enabled = true; } else { @@ -874,7 +884,10 @@ void ObjectManipulation::update_if_dirty() m_lock_bnt->SetLock(m_uniform_scale); m_lock_bnt->SetToolTip(wxEmptyString); m_lock_bnt->enable(); -#if !ENABLE_WORLD_COORDINATE +#if ENABLE_WORLD_COORDINATE + if (m_word_local_combo->GetSelection() != (int)m_coordinates_type) + m_word_local_combo->SetSelection((int)m_coordinates_type); +#else } { @@ -882,7 +895,7 @@ void ObjectManipulation::update_if_dirty() if (m_word_local_combo->GetSelection() != new_selection) m_word_local_combo->SetSelection(new_selection); } -#endif // !ENABLE_WORLD_COORDINATE +#endif // ENABLE_WORLD_COORDINATE if (m_new_enabled) m_og->enable(); @@ -1027,7 +1040,13 @@ void ObjectManipulation::update_mirror_buttons_visibility() #endif // !ENABLE_WORLD_COORDINATE } } -#if !ENABLE_WORLD_COORDINATE + +#if ENABLE_WORLD_COORDINATE + const bool can_mirror = wxGetApp().plater()->can_mirror(); + for (ScalableButton* button : m_mirror_buttons) { + button->Enable(can_mirror); + } +#else else { // the mirroring buttons should be hidden in world coordinates, // unless we make it actually mirror in world coords. @@ -1049,7 +1068,7 @@ void ObjectManipulation::update_mirror_buttons_visibility() } } }); -#endif // !ENABLE_WORLD_COORDINATE +#endif // ENABLE_WORLD_COORDINATE } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 952a903bb..cec9b8f2f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -129,7 +129,7 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent) , m_update_job_cancel(nullptr) { m_rotate_gizmo.set_group_id(0); - m_rotate_gizmo.set_using_local_coordinate(true); + m_rotate_gizmo.set_force_local_coordinate(true); // TODO: add suggestion to use https://fontawesome.com/ // (copy & paste) unicode symbols from web // paste HEX unicode into notepad move cursor after unicode press [alt] + [x] @@ -300,7 +300,8 @@ bool GLGizmoEmboss::on_mouse_for_rotation(const wxMouseEvent &mouse_event) angle -= PI / 2; // Grabber is upward // temporary rotation - TransformationType transformation_type = TransformationType::Local_Relative_Joint; + const TransformationType transformation_type = m_parent.get_selection().is_single_text() ? + TransformationType::Local_Relative_Joint : TransformationType::World_Relative_Joint; m_parent.get_selection().rotate(Vec3d(0., 0., angle), transformation_type); angle += *m_rotate_start_angle; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 69fcc5414..7656226b5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -149,7 +149,10 @@ void GLGizmoMove3D::on_render() glsafe(::glEnable(GL_DEPTH_TEST)); #if ENABLE_WORLD_COORDINATE - calc_selection_box_and_center(); + const Selection& selection = m_parent.get_selection(); + const auto& [box, box_trafo] = selection.get_bounding_box_in_current_reference_system(); + m_bounding_box = box; + m_center = box_trafo.translation(); const Transform3d base_matrix = local_transform(m_parent.get_selection()); for (int i = 0; i < 3; ++i) { m_grabbers[i].matrix = base_matrix; @@ -363,33 +366,6 @@ Transform3d GLGizmoMove3D::local_transform(const Selection& selection) const } return ret; } - -void GLGizmoMove3D::calc_selection_box_and_center() -{ - const Selection& selection = m_parent.get_selection(); - const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); - if (coordinates_type == ECoordinatesType::World) { - m_bounding_box = selection.get_bounding_box(); - m_center = m_bounding_box.center(); - } - else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { - const GLVolume& v = *selection.get_first_volume(); - m_bounding_box = v.transformed_convex_hull_bounding_box( - v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_scaling_factor_matrix()); - m_center = v.world_matrix() * m_bounding_box.center(); - } - else { - m_bounding_box.reset(); - const Selection::IndicesList& ids = selection.get_volume_idxs(); - for (unsigned int id : ids) { - const GLVolume& v = *selection.get_volume(id); - m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); - } - const Geometry::Transformation inst_trafo = selection.get_first_volume()->get_instance_transformation(); - m_bounding_box = m_bounding_box.transformed(inst_trafo.get_scaling_factor_matrix()); - m_center = inst_trafo.get_matrix_no_scaling_factor() * m_bounding_box.center(); - } -} #endif // ENABLE_WORLD_COORDINATE } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index 5f1d562e9..cd92d7472 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -67,7 +67,6 @@ private: double calc_projection(const UpdateData& data) const; #if ENABLE_WORLD_COORDINATE Transform3d local_transform(const Selection& selection) const; - void calc_selection_box_and_center(); #endif // ENABLE_WORLD_COORDINATE }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 0be1d1655..345d733af 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -234,50 +234,17 @@ void GLGizmoRotate::on_render() #if ENABLE_WORLD_COORDINATE void GLGizmoRotate::init_data_from_selection(const Selection& selection) { - ECoordinatesType coordinates_type; - if (m_using_local_coordinate || - selection.is_wipe_tower()) - coordinates_type = ECoordinatesType::Local; - else - coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); - if (coordinates_type == ECoordinatesType::World) { - m_bounding_box = selection.get_bounding_box(); - m_center = m_bounding_box.center(); - } - else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { - const GLVolume& v = *selection.get_first_volume(); - m_bounding_box = v.transformed_convex_hull_bounding_box( - v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_scaling_factor_matrix()); - m_center = v.world_matrix() * m_bounding_box.center(); - } - else { - m_bounding_box.reset(); - const Selection::IndicesList& ids = selection.get_volume_idxs(); - for (unsigned int id : ids) { - const GLVolume& v = *selection.get_volume(id); - m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); - } - const Geometry::Transformation inst_trafo = selection.get_first_volume()->get_instance_transformation(); - m_bounding_box = m_bounding_box.transformed(inst_trafo.get_scaling_factor_matrix()); - m_center = inst_trafo.get_matrix_no_scaling_factor() * m_bounding_box.center(); - } + const auto [box, box_trafo] = m_force_local_coordinate ? + selection.get_bounding_box_in_reference_system(ECoordinatesType::Local) : selection.get_bounding_box_in_current_reference_system(); + m_bounding_box = box; + m_center = box_trafo.translation(); + m_orient_matrix = box_trafo; m_radius = Offset + m_bounding_box.radius(); m_snap_coarse_in_radius = m_radius / 3.0f; m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; m_snap_fine_in_radius = m_radius; m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; - - if (coordinates_type == ECoordinatesType::World) - m_orient_matrix = Transform3d::Identity(); - else if (coordinates_type == ECoordinatesType::Local && (selection.is_wipe_tower() || selection.is_single_volume_or_modifier())) { - const GLVolume& v = *selection.get_first_volume(); - m_orient_matrix = v.get_instance_transformation().get_rotation_matrix() * v.get_volume_transformation().get_rotation_matrix(); - } - else { - const GLVolume& v = *selection.get_first_volume(); - m_orient_matrix = v.get_instance_transformation().get_rotation_matrix(); - } } #endif // ENABLE_WORLD_COORDINATE @@ -531,7 +498,7 @@ Transform3d GLGizmoRotate::local_transform(const Selection& selection) const } #if ENABLE_WORLD_COORDINATE - return Geometry::translation_transform(m_center) * m_orient_matrix * ret; + return m_orient_matrix * ret; #else if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) ret = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true) * ret; @@ -546,7 +513,7 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray) cons Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const #endif // ENABLE_WORLD_COORDINATE { - double half_pi = 0.5 * double(PI); + const double half_pi = 0.5 * double(PI); Transform3d m = Transform3d::Identity(); @@ -573,7 +540,7 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons } #if ENABLE_WORLD_COORDINATE - m = m * m_orient_matrix.inverse(); + m = m * Geometry::Transformation(m_orient_matrix).get_matrix_no_offset().inverse(); #else if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) m = m * selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true).inverse(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index fa52e3a78..ebfed1920 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -56,7 +56,7 @@ private: float m_old_angle{ 0.0f }; // emboss need to draw rotation gizmo in local coordinate systems - bool m_using_local_coordinate{false}; + bool m_force_local_coordinate{ false }; ColorRGBA m_drag_color; ColorRGBA m_highlight_color; @@ -71,7 +71,7 @@ public: std::string get_tooltip() const override; void set_group_id(int group_id) { m_group_id = group_id; } - void set_using_local_coordinate(bool use) { m_using_local_coordinate =use;} + void set_force_local_coordinate(bool use) { m_force_local_coordinate = use; } void start_dragging(); void stop_dragging(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 1787e5cf8..173585ec0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -206,6 +206,7 @@ void GLGizmoScale3D::on_dragging(const UpdateData& data) do_scale_uniform(data); } +#if ENABLE_WORLD_COORDINATE void GLGizmoScale3D::on_render() { const Selection& selection = m_parent.get_selection(); @@ -213,98 +214,20 @@ void GLGizmoScale3D::on_render() glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); - m_bounding_box.reset(); -#if ENABLE_WORLD_COORDINATE - m_grabbers_transform = Transform3d::Identity(); - m_center = Vec3d::Zero(); + const auto& [box, box_trafo] = selection.get_bounding_box_in_current_reference_system(); + m_bounding_box = box; + m_center = box_trafo.translation(); + m_grabbers_transform = box_trafo; m_instance_center = Vec3d::Zero(); - if (selection.is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) { -#else - m_transform = Transform3d::Identity(); - // Transforms grabbers' offsets to world refefence system - Transform3d offsets_transform = Transform3d::Identity(); - m_offsets_transform = Transform3d::Identity(); - Vec3d angles = Vec3d::Zero(); - - if (selection.is_single_full_instance()) { -#endif // ENABLE_WORLD_COORDINATE - // calculate bounding box in instance local reference system - const Selection::IndicesList& idxs = selection.get_volume_idxs(); - for (unsigned int idx : idxs) { - const GLVolume& v = *selection.get_volume(idx); - m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); - } - -#if ENABLE_WORLD_COORDINATE - m_bounding_box = m_bounding_box.transformed(selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix()); -#endif // ENABLE_WORLD_COORDINATE - - // gets transform from first selected volume - const GLVolume& v = *selection.get_first_volume(); -#if ENABLE_WORLD_COORDINATE - const Transform3d inst_trafo = v.get_instance_transformation().get_matrix_no_scaling_factor(); - m_grabbers_transform = inst_trafo * Geometry::translation_transform(m_bounding_box.center()); - m_center = inst_trafo * m_bounding_box.center(); - m_instance_center = v.get_instance_offset(); - } - else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_instance_coordinates()) { -#else - m_transform = v.get_instance_transformation().get_matrix(); - - // gets angles from first selected volume - angles = v.get_instance_rotation(); - // consider rotation+mirror only components of the transform for offsets - offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror()); - m_offsets_transform = offsets_transform; - } - else if (selection.is_single_modifier() || selection.is_single_volume()) { -#endif // ENABLE_WORLD_COORDINATE - const GLVolume& v = *selection.get_first_volume(); -#if ENABLE_WORLD_COORDINATE - m_bounding_box.merge(v.transformed_convex_hull_bounding_box( - v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_matrix_no_offset())); - Geometry::Transformation trafo(v.get_instance_transformation().get_rotation_matrix()); - trafo.set_offset(v.world_matrix().translation()); - m_grabbers_transform = trafo.get_matrix(); - m_center = v.world_matrix() * m_bounding_box.center(); + if (selection.is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) + m_instance_center = selection.get_first_volume()->get_instance_offset(); + else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_instance_coordinates()) m_instance_center = m_center; - } - else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates()) { - const GLVolume& v = *selection.get_first_volume(); - m_bounding_box.merge(v.transformed_convex_hull_bounding_box( - v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_scaling_factor_matrix())); - Geometry::Transformation trafo(v.get_instance_transformation().get_rotation_matrix() * v.get_volume_transformation().get_rotation_matrix()); - trafo.set_offset(v.world_matrix().translation()); - m_grabbers_transform = trafo.get_matrix(); - m_center = v.world_matrix() * m_bounding_box.center(); + else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates()) m_instance_center = m_center; - } - else { - m_bounding_box = selection.get_bounding_box(); - m_grabbers_transform = Geometry::translation_transform(m_bounding_box.center()); - m_center = m_bounding_box.center(); - m_instance_center = selection.is_single_full_instance() ? selection.get_first_volume()->get_instance_offset() : m_center; - } -#else - m_bounding_box = v.bounding_box(); - m_transform = v.world_matrix(); - angles = Geometry::extract_rotation(m_transform); - // consider rotation+mirror only components of the transform for offsets - offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror()); - m_offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), v.get_volume_rotation(), Vec3d::Ones(), v.get_volume_mirror()); - } else - m_bounding_box = selection.get_bounding_box(); + m_instance_center = selection.is_single_full_instance() ? selection.get_first_volume()->get_instance_offset() : m_center; - const Vec3d& center = m_bounding_box.center(); - const Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0); - const Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0); - const Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset); - - const bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL)); -#endif // ENABLE_WORLD_COORDINATE - -#if ENABLE_WORLD_COORDINATE // x axis const Vec3d box_half_size = 0.5 * m_bounding_box.size(); bool use_constrain = wxGetKeyState(WXK_CONTROL) && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()); @@ -335,57 +258,18 @@ void GLGizmoScale3D::on_render() m_grabbers[8].color = (use_constrain && m_hover_id == 6) ? CONSTRAINED_COLOR : m_highlight_color; m_grabbers[9].center = { -(box_half_size.x() + Offset), box_half_size.y() + Offset, 0.0 }; m_grabbers[9].color = (use_constrain && m_hover_id == 7) ? CONSTRAINED_COLOR : m_highlight_color; -#else - // x axis - m_grabbers[0].center = m_transform * Vec3d(m_bounding_box.min.x(), center.y(), center.z()) - offset_x; - m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0]; - m_grabbers[1].center = m_transform * Vec3d(m_bounding_box.max.x(), center.y(), center.z()) + offset_x; - m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0]; - - // y axis - m_grabbers[2].center = m_transform * Vec3d(center.x(), m_bounding_box.min.y(), center.z()) - offset_y; - m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1]; - m_grabbers[3].center = m_transform * Vec3d(center.x(), m_bounding_box.max.y(), center.z()) + offset_y; - m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1]; - - // z axis - m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.min.z()) - offset_z; - m_grabbers[4].color = (ctrl_down && m_hover_id == 5) ? CONSTRAINED_COLOR : AXES_COLOR[2]; - m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.max.z()) + offset_z; - m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2]; - - // uniform - m_grabbers[6].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.min.y(), center.z()) - offset_x - offset_y; - m_grabbers[7].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.min.y(), center.z()) + offset_x - offset_y; - m_grabbers[8].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.max.y(), center.z()) + offset_x + offset_y; - m_grabbers[9].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.max.y(), center.z()) - offset_x + offset_y; - - for (int i = 6; i < 10; ++i) { - m_grabbers[i].color = m_highlight_color; - } - - // sets grabbers orientation - for (int i = 0; i < 10; ++i) { - m_grabbers[i].angles = angles; - } -#endif // ENABLE_WORLD_COORDINATE #if ENABLE_GL_CORE_PROFILE if (!OpenGLManager::get_gl_info().is_core_profile()) #endif // ENABLE_GL_CORE_PROFILE glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); -#if ENABLE_WORLD_COORDINATE const Transform3d base_matrix = local_transform(selection); for (int i = 0; i < 10; ++i) { m_grabbers[i].matrix = base_matrix; } const float grabber_mean_size = (float)((m_bounding_box.size().x() + m_bounding_box.size().y() + m_bounding_box.size().z()) / 3.0); -#else - const BoundingBoxf3& selection_box = selection.get_bounding_box(); - const float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0); -#endif // ENABLE_WORLD_COORDINATE if (m_hover_id == -1) { // draw connections @@ -397,11 +281,7 @@ void GLGizmoScale3D::on_render() if (shader != nullptr) { shader->start_using(); const Camera& camera = wxGetApp().plater()->get_camera(); -#if ENABLE_WORLD_COORDINATE shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix); -#else - shader->set_uniform("view_model_matrix", camera.get_view_matrix()); -#endif // ENABLE_WORLD_COORDINATE shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #if ENABLE_GL_CORE_PROFILE const std::array& viewport = camera.get_viewport(); @@ -435,11 +315,7 @@ void GLGizmoScale3D::on_render() if (shader != nullptr) { shader->start_using(); const Camera& camera = wxGetApp().plater()->get_camera(); -#if ENABLE_WORLD_COORDINATE shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix); -#else - shader->set_uniform("view_model_matrix", camera.get_view_matrix()); -#endif // ENABLE_WORLD_COORDINATE shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #if ENABLE_GL_CORE_PROFILE const std::array& viewport = camera.get_viewport(); @@ -471,11 +347,7 @@ void GLGizmoScale3D::on_render() if (shader != nullptr) { shader->start_using(); const Camera& camera = wxGetApp().plater()->get_camera(); -#if ENABLE_WORLD_COORDINATE shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix); -#else - shader->set_uniform("view_model_matrix", camera.get_view_matrix()); -#endif // ENABLE_WORLD_COORDINATE shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #if ENABLE_GL_CORE_PROFILE const std::array& viewport = camera.get_viewport(); @@ -507,11 +379,7 @@ void GLGizmoScale3D::on_render() if (shader != nullptr) { shader->start_using(); const Camera& camera = wxGetApp().plater()->get_camera(); -#if ENABLE_WORLD_COORDINATE shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix); -#else - shader->set_uniform("view_model_matrix", camera.get_view_matrix()); -#endif // ENABLE_WORLD_COORDINATE shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #if ENABLE_GL_CORE_PROFILE const std::array& viewport = camera.get_viewport(); @@ -543,11 +411,7 @@ void GLGizmoScale3D::on_render() if (shader != nullptr) { shader->start_using(); const Camera& camera = wxGetApp().plater()->get_camera(); -#if ENABLE_WORLD_COORDINATE shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix); -#else - shader->set_uniform("view_model_matrix", camera.get_view_matrix()); -#endif // ENABLE_WORLD_COORDINATE shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #if ENABLE_GL_CORE_PROFILE const std::array& viewport = camera.get_viewport(); @@ -574,6 +438,267 @@ void GLGizmoScale3D::on_render() } } } +#else +void GLGizmoScale3D::on_render() +{ + const Selection& selection = m_parent.get_selection(); + + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); + glsafe(::glEnable(GL_DEPTH_TEST)); + + m_bounding_box.reset(); + m_transform = Transform3d::Identity(); + // Transforms grabbers' offsets to world refefence system + Transform3d offsets_transform = Transform3d::Identity(); + m_offsets_transform = Transform3d::Identity(); + Vec3d angles = Vec3d::Zero(); + + if (selection.is_single_full_instance()) { + // calculate bounding box in instance local reference system + const Selection::IndicesList& idxs = selection.get_volume_idxs(); + for (unsigned int idx : idxs) { + const GLVolume& v = *selection.get_volume(idx); + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); + } + + // gets transform from first selected volume + const GLVolume& v = *selection.get_first_volume(); + m_transform = v.get_instance_transformation().get_matrix(); + + // gets angles from first selected volume + angles = v.get_instance_rotation(); + // consider rotation+mirror only components of the transform for offsets + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror()); + m_offsets_transform = offsets_transform; + } + else if (selection.is_single_modifier() || selection.is_single_volume()) { + const GLVolume& v = *selection.get_first_volume(); + m_bounding_box = v.bounding_box(); + m_transform = v.world_matrix(); + angles = Geometry::extract_rotation(m_transform); + // consider rotation+mirror only components of the transform for offsets + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror()); + m_offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), v.get_volume_rotation(), Vec3d::Ones(), v.get_volume_mirror()); + } + else + m_bounding_box = selection.get_bounding_box(); + + const Vec3d& center = m_bounding_box.center(); + const Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0); + const Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0); + const Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset); + + const bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL)); + + // x axis + m_grabbers[0].center = m_transform * Vec3d(m_bounding_box.min.x(), center.y(), center.z()) - offset_x; + m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0]; + m_grabbers[1].center = m_transform * Vec3d(m_bounding_box.max.x(), center.y(), center.z()) + offset_x; + m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0]; + + // y axis + m_grabbers[2].center = m_transform * Vec3d(center.x(), m_bounding_box.min.y(), center.z()) - offset_y; + m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1]; + m_grabbers[3].center = m_transform * Vec3d(center.x(), m_bounding_box.max.y(), center.z()) + offset_y; + m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1]; + + // z axis + m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.min.z()) - offset_z; + m_grabbers[4].color = (ctrl_down && m_hover_id == 5) ? CONSTRAINED_COLOR : AXES_COLOR[2]; + m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.max.z()) + offset_z; + m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2]; + + // uniform + m_grabbers[6].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.min.y(), center.z()) - offset_x - offset_y; + m_grabbers[7].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.min.y(), center.z()) + offset_x - offset_y; + m_grabbers[8].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.max.y(), center.z()) + offset_x + offset_y; + m_grabbers[9].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.max.y(), center.z()) - offset_x + offset_y; + + for (int i = 6; i < 10; ++i) { + m_grabbers[i].color = m_highlight_color; + } + + // sets grabbers orientation + for (int i = 0; i < 10; ++i) { + m_grabbers[i].angles = angles; + } + +#if ENABLE_GL_CORE_PROFILE + if (!OpenGLManager::get_gl_info().is_core_profile()) +#endif // ENABLE_GL_CORE_PROFILE + glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); + + const BoundingBoxf3& selection_box = selection.get_bounding_box(); + const float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0); + + if (m_hover_id == -1) { + // draw connections +#if ENABLE_GL_CORE_PROFILE + GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); +#else + GLShaderProgram* shader = wxGetApp().get_shader("flat"); +#endif // ENABLE_GL_CORE_PROFILE + if (shader != nullptr) { + shader->start_using(); + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); +#if ENABLE_GL_CORE_PROFILE + const std::array& viewport = camera.get_viewport(); + shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); + shader->set_uniform("width", 0.25f); + shader->set_uniform("gap_size", 0.0f); +#endif // ENABLE_GL_CORE_PROFILE + if (m_grabbers[0].enabled && m_grabbers[1].enabled) + render_grabbers_connection(0, 1, m_grabbers[0].color); + if (m_grabbers[2].enabled && m_grabbers[3].enabled) + render_grabbers_connection(2, 3, m_grabbers[2].color); + if (m_grabbers[4].enabled && m_grabbers[5].enabled) + render_grabbers_connection(4, 5, m_grabbers[4].color); + render_grabbers_connection(6, 7, m_base_color); + render_grabbers_connection(7, 8, m_base_color); + render_grabbers_connection(8, 9, m_base_color); + render_grabbers_connection(9, 6, m_base_color); + shader->stop_using(); + } + + // draw grabbers + render_grabbers(grabber_mean_size); + } + else if ((m_hover_id == 0 || m_hover_id == 1) && m_grabbers[0].enabled && m_grabbers[1].enabled) { + // draw connections +#if ENABLE_GL_CORE_PROFILE + GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); +#else + GLShaderProgram* shader = wxGetApp().get_shader("flat"); +#endif // ENABLE_GL_CORE_PROFILE + if (shader != nullptr) { + shader->start_using(); + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); +#if ENABLE_GL_CORE_PROFILE + const std::array& viewport = camera.get_viewport(); + shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); + shader->set_uniform("width", 0.25f); + shader->set_uniform("gap_size", 0.0f); +#endif // ENABLE_GL_CORE_PROFILE + render_grabbers_connection(0, 1, m_grabbers[0].color); + shader->stop_using(); + } + + // draw grabbers + shader = wxGetApp().get_shader("gouraud_light"); + if (shader != nullptr) { + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); + m_grabbers[0].render(true, grabber_mean_size); + m_grabbers[1].render(true, grabber_mean_size); + shader->stop_using(); + } + } + else if ((m_hover_id == 2 || m_hover_id == 3) && m_grabbers[2].enabled && m_grabbers[3].enabled) { + // draw connections +#if ENABLE_GL_CORE_PROFILE + GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); +#else + GLShaderProgram* shader = wxGetApp().get_shader("flat"); +#endif // ENABLE_GL_CORE_PROFILE + if (shader != nullptr) { + shader->start_using(); + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); +#if ENABLE_GL_CORE_PROFILE + const std::array& viewport = camera.get_viewport(); + shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); + shader->set_uniform("width", 0.25f); + shader->set_uniform("gap_size", 0.0f); +#endif // ENABLE_GL_CORE_PROFILE + render_grabbers_connection(2, 3, m_grabbers[2].color); + shader->stop_using(); + } + + // draw grabbers + shader = wxGetApp().get_shader("gouraud_light"); + if (shader != nullptr) { + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); + m_grabbers[2].render(true, grabber_mean_size); + m_grabbers[3].render(true, grabber_mean_size); + shader->stop_using(); + } + } + else if ((m_hover_id == 4 || m_hover_id == 5) && m_grabbers[4].enabled && m_grabbers[5].enabled) { + // draw connections +#if ENABLE_GL_CORE_PROFILE + GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); +#else + GLShaderProgram* shader = wxGetApp().get_shader("flat"); +#endif // ENABLE_GL_CORE_PROFILE + if (shader != nullptr) { + shader->start_using(); + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); +#if ENABLE_GL_CORE_PROFILE + const std::array& viewport = camera.get_viewport(); + shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); + shader->set_uniform("width", 0.25f); + shader->set_uniform("gap_size", 0.0f); +#endif // ENABLE_GL_CORE_PROFILE + render_grabbers_connection(4, 5, m_grabbers[4].color); + shader->stop_using(); + } + + // draw grabbers + shader = wxGetApp().get_shader("gouraud_light"); + if (shader != nullptr) { + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); + m_grabbers[4].render(true, grabber_mean_size); + m_grabbers[5].render(true, grabber_mean_size); + shader->stop_using(); + } + } + else if (m_hover_id >= 6) { + // draw connections +#if ENABLE_GL_CORE_PROFILE + GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); +#else + GLShaderProgram* shader = wxGetApp().get_shader("flat"); +#endif // ENABLE_GL_CORE_PROFILE + if (shader != nullptr) { + shader->start_using(); + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); +#if ENABLE_GL_CORE_PROFILE + const std::array& viewport = camera.get_viewport(); + shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); + shader->set_uniform("width", 0.25f); + shader->set_uniform("gap_size", 0.0f); +#endif // ENABLE_GL_CORE_PROFILE + render_grabbers_connection(6, 7, m_drag_color); + render_grabbers_connection(7, 8, m_drag_color); + render_grabbers_connection(8, 9, m_drag_color); + render_grabbers_connection(9, 6, m_drag_color); + shader->stop_using(); + } + + // draw grabbers + shader = wxGetApp().get_shader("gouraud_light"); + if (shader != nullptr) { + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); + for (int i = 6; i < 10; ++i) { + m_grabbers[i].render(true, grabber_mean_size); + } + shader->stop_using(); + } + } +} +#endif // ENABLE_WORLD_COORDINATE void GLGizmoScale3D::on_register_raycasters_for_picking() { diff --git a/src/slic3r/GUI/Mouse3DController.cpp b/src/slic3r/GUI/Mouse3DController.cpp index e5ad5d64f..1ce671753 100644 --- a/src/slic3r/GUI/Mouse3DController.cpp +++ b/src/slic3r/GUI/Mouse3DController.cpp @@ -668,6 +668,11 @@ void Mouse3DController::init() #ifndef _WIN32 // Don't start the background thread on Windows, as the HID messages are sent as Windows messages. m_thread = std::thread(&Mouse3DController::run, this); +#else + // For some reason, HID message routing does not work well with remote session. Requires further investigation + if (::GetSystemMetrics(SM_REMOTESESSION)) { + m_thread = std::thread(&Mouse3DController::run, this); + } #endif // _WIN32 } } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index ed280697a..b55f6299a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4837,9 +4837,14 @@ bool Plater::priv::layers_height_allowed() const bool Plater::priv::can_mirror() const { +#if ENABLE_WORLD_COORDINATE + return !sidebar->obj_list()->has_selected_cut_object(); +#else return !sidebar->obj_list()->has_selected_cut_object() && get_selection().is_from_single_instance(); +#endif // ENABLE_WORLD_COORDINATE } + bool Plater::priv::can_replace_with_stl() const { return !sidebar->obj_list()->has_selected_cut_object() && get_selection().get_volume_idxs().size() == 1; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 3c5c11a6b..106937c46 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -562,7 +562,7 @@ void PreferencesDialog::build() if (opt_key == "suppress_hyperlinks") m_values[opt_key] = boost::any_cast(value) ? "1" : ""; else - m_values[opt_key] = boost::any_cast(value) ? "1" : "0"; m_values[opt_key] = boost::any_cast(value) ? "1" : "0"; + m_values[opt_key] = boost::any_cast(value) ? "1" : "0"; }; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 2e92c8b6b..fda11421f 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -801,6 +801,133 @@ const BoundingBoxf3& Selection::get_full_unscaled_instance_local_bounding_box() } return *m_full_unscaled_instance_local_bounding_box; } + +const std::pair& Selection::get_bounding_box_in_current_reference_system() const +{ + static int last_coordinates_type = -1; + + assert(!is_empty()); + + ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); + if (m_mode == Instance && coordinates_type == ECoordinatesType::Local) + coordinates_type = ECoordinatesType::World; + + if (last_coordinates_type != int(coordinates_type)) + const_cast>*>(&m_bounding_box_in_current_reference_system)->reset(); + + if (!m_bounding_box_in_current_reference_system.has_value()) { + last_coordinates_type = int(coordinates_type); + *const_cast>*>(&m_bounding_box_in_current_reference_system) = get_bounding_box_in_reference_system(coordinates_type); + } + + return *m_bounding_box_in_current_reference_system; +} + +std::pair Selection::get_bounding_box_in_reference_system(ECoordinatesType type) const +{ + BoundingBoxf3 original_box; + Transform3d trafo; + + // + // calculate box aligned to current reference system + // + switch (type) + { + case ECoordinatesType::World: + { + original_box = get_bounding_box(); + trafo = Transform3d::Identity(); + break; + } + case ECoordinatesType::Instance: { + for (unsigned int id : m_list) { + const GLVolume& v = *get_volume(id); + original_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); + } + trafo = get_first_volume()->get_instance_transformation().get_matrix(); + break; + } + case ECoordinatesType::Local: { + assert(is_single_volume_or_modifier() || is_single_volume_instance()); + const GLVolume& v = *get_first_volume(); + original_box = v.bounding_box(); + trafo = v.world_matrix(); + break; + } + } + + // + // calculate box size in world coordinates + // + auto point_to_Vec4d = [](const Vec3d& p) { return Vec4d(p.x(), p.y(), p.z(), 1.0); }; + auto Vec4d_to_Vec3d = [](const Vec4d& v) { return Vec3d(v.x(), v.y(), v.z()); }; + + auto apply_transform = [](const std::vector& original, const Transform3d& trafo, bool normalize) { + std::vector transformed(original.size()); + for (size_t i = 0; i < original.size(); ++i) { + transformed[i] = trafo * original[i]; + if (normalize) + transformed[i].normalize(); + } + return transformed; + }; + + auto calc_box_size = [point_to_Vec4d, Vec4d_to_Vec3d, apply_transform](const BoundingBoxf3& box, const Transform3d& trafo) { + Geometry::Transformation transformation(trafo); + + // box aligned to current reference system + std::vector homo_vertices = { + point_to_Vec4d({ box.min.x(), box.min.y(), box.min.z() }), + point_to_Vec4d({ box.max.x(), box.min.y(), box.min.z() }), + point_to_Vec4d({ box.max.x(), box.max.y(), box.min.z() }), + point_to_Vec4d({ box.min.x(), box.max.y(), box.min.z() }), + point_to_Vec4d({ box.min.x(), box.min.y(), box.max.z() }), + point_to_Vec4d({ box.max.x(), box.min.y(), box.max.z() }), + point_to_Vec4d({ box.max.x(), box.max.y(), box.max.z() }), + point_to_Vec4d({ box.min.x(), box.max.y(), box.max.z() }) + }; + + // box vertices in world coordinates + std::vector transformed_homo_vertices = apply_transform(homo_vertices, trafo, false); + + // project back to current reference system + const std::vector homo_axes = { Vec4d::UnitX(), Vec4d::UnitY(), Vec4d::UnitZ() }; + std::vector transformed_homo_axes = apply_transform(homo_axes, Geometry::Transformation(trafo).get_matrix_no_scaling_factor(), true); + std::vector transformed_axes(transformed_homo_axes.size()); + for (size_t i = 0; i < transformed_homo_axes.size(); ++i) { + transformed_axes[i] = Vec4d_to_Vec3d(transformed_homo_axes[i]); + } + + Vec3d min = { DBL_MAX, DBL_MAX, DBL_MAX }; + Vec3d max = { -DBL_MAX, -DBL_MAX, -DBL_MAX }; + + for (const Vec4d& v_homo : transformed_homo_vertices) { + const Vec3d v = Vec4d_to_Vec3d(v_homo); + for (int i = 0; i < 3; ++i) { + const double dot_i = v.dot(transformed_axes[i]); + min(i) = std::min(min(i), dot_i); + max(i) = std::max(max(i), dot_i); + } + } + + // return size + const Vec3d size = max - min; + return size; + }; + + const Vec3d box_size = calc_box_size(original_box, trafo); + const std::vector box_center = { point_to_Vec4d(original_box.center()) }; + std::vector transformed_box_center = apply_transform(box_center, trafo, false); + + // + // return box centered at 0, 0, 0 + // + const Vec3d half_box_size = 0.5 * box_size; + BoundingBoxf3 out_box(-half_box_size, half_box_size); + Geometry::Transformation out_trafo(trafo); + out_trafo.set_offset(Vec4d_to_Vec3d(transformed_box_center[0])); + return { out_box, out_trafo.get_matrix_no_scaling_factor() }; +} #endif // ENABLE_WORLD_COORDINATE void Selection::setup_cache() @@ -836,7 +963,8 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor else { if (transformation_type.local()) { const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform(); - v.set_volume_offset(vol_trafo.get_offset() + vol_trafo.get_rotation_matrix() * displacement); + const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform(); + v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement); } else { Vec3d relative_disp = displacement; @@ -1724,27 +1852,7 @@ void Selection::render(float scale_factor) m_scale_factor = scale_factor; // render cumulative bounding box of selected volumes #if ENABLE_WORLD_COORDINATE - BoundingBoxf3 box; - Transform3d trafo; - const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); - if (coordinates_type == ECoordinatesType::World) { - box = get_bounding_box(); - trafo = Transform3d::Identity(); - } - else if (coordinates_type == ECoordinatesType::Local && is_single_volume_or_modifier()) { - const GLVolume& v = *get_first_volume(); - box = v.bounding_box(); - trafo = v.world_matrix(); - } - else { - const Selection::IndicesList& ids = get_volume_idxs(); - for (unsigned int id : ids) { - const GLVolume& v = *get_volume(id); - box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); - } - trafo = get_first_volume()->get_instance_transformation().get_matrix(); - } - + const auto& [box, trafo] = get_bounding_box_in_current_reference_system(); render_bounding_box(box, trafo, ColorRGB::WHITE()); #else render_bounding_box(get_bounding_box(), ColorRGB::WHITE()); @@ -2051,8 +2159,7 @@ void Selection::update_type() if (!m_valid) m_type = Invalid; - else - { + else { if (m_list.empty()) m_type = Empty; else if (m_list.size() == 1) { @@ -2068,12 +2175,12 @@ void Selection::update_type() unsigned int volumes_count = (unsigned int)model_object->volumes.size(); unsigned int instances_count = (unsigned int)model_object->instances.size(); if (volumes_count * instances_count == 1) { + const ModelVolume* model_volume = model_object->volumes[first->volume_idx()]; m_type = SingleFullObject; // ensures the correct mode is selected m_mode = Instance; } - else if (volumes_count == 1) // instances_count > 1 - { + else if (volumes_count == 1) { // instances_count > 1 m_type = SingleFullInstance; // ensures the correct mode is selected m_mode = Instance; @@ -2669,88 +2776,88 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field, GL #if ENABLE_WORLD_COORDINATE_DEBUG void Selection::render_debug_window() const { - if (m_list.empty()) - return; + if (m_list.empty()) + return; - if (get_first_volume()->is_wipe_tower) - return; + if (get_first_volume()->is_wipe_tower) + return; - ImGuiWrapper& imgui = *wxGetApp().imgui(); - imgui.begin(std::string("Selection matrices"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize); + ImGuiWrapper& imgui = *wxGetApp().imgui(); + imgui.begin(std::string("Selection matrices"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize); - auto volume_name = [this](size_t id) { - const GLVolume& v = *(*m_volumes)[id]; - return m_model->objects[v.object_idx()]->volumes[v.volume_idx()]->name; - }; + auto volume_name = [this](size_t id) { + const GLVolume& v = *(*m_volumes)[id]; + return m_model->objects[v.object_idx()]->volumes[v.volume_idx()]->name; + }; - static size_t current_cmb_idx = 0; - static size_t current_vol_idx = *m_list.begin(); + static size_t current_cmb_idx = 0; + static size_t current_vol_idx = *m_list.begin(); - if (m_list.find(current_vol_idx) == m_list.end()) - current_vol_idx = *m_list.begin(); + if (m_list.find(current_vol_idx) == m_list.end()) + current_vol_idx = *m_list.begin(); - if (ImGui::BeginCombo("Volumes", volume_name(current_vol_idx).c_str())) { - size_t count = 0; - for (unsigned int id : m_list) { - const GLVolume& v = *(*m_volumes)[id]; - const bool is_selected = (current_cmb_idx == count); - if (ImGui::Selectable(volume_name(id).c_str(), is_selected)) { - current_cmb_idx = count; - current_vol_idx = id; - } - if (is_selected) - ImGui::SetItemDefaultFocus(); - ++count; - } - ImGui::EndCombo(); - } - - static int current_method_idx = 0; - ImGui::Combo("Decomposition method", ¤t_method_idx, "computeRotationScaling\0computeScalingRotation\0"); - - const GLVolume& v = *get_volume(current_vol_idx); - - auto add_matrix = [&imgui](const std::string& name, const Transform3d& m, unsigned int size) { - ImGui::BeginGroup(); - imgui.text(name); - if (ImGui::BeginTable(name.c_str(), size, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInner)) { - for (unsigned int r = 0; r < size; ++r) { - ImGui::TableNextRow(); - for (unsigned int c = 0; c < size; ++c) { - ImGui::TableSetColumnIndex(c); - imgui.text(std::to_string(m(r, c))); + if (ImGui::BeginCombo("Volumes", volume_name(current_vol_idx).c_str())) { + size_t count = 0; + for (unsigned int id : m_list) { + const GLVolume& v = *(*m_volumes)[id]; + const bool is_selected = (current_cmb_idx == count); + if (ImGui::Selectable(volume_name(id).c_str(), is_selected)) { + current_cmb_idx = count; + current_vol_idx = id; + } + if (is_selected) + ImGui::SetItemDefaultFocus(); + ++count; } - } - ImGui::EndTable(); + ImGui::EndCombo(); } - ImGui::EndGroup(); - }; - auto add_matrices_set = [add_matrix](const std::string& name, const Transform3d& m, size_t method) { - static unsigned int counter = 0; - ++counter; - if (ImGui::CollapsingHeader(name.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) { - add_matrix("Full", m, 4); + static int current_method_idx = 0; + ImGui::Combo("Decomposition method", ¤t_method_idx, "computeRotationScaling\0computeScalingRotation\0"); - Matrix3d rotation; - Matrix3d scale; - if (method == 0) - m.computeRotationScaling(&rotation, &scale); - else - m.computeScalingRotation(&scale, &rotation); + const GLVolume& v = *get_volume(current_vol_idx); - ImGui::SameLine(); - add_matrix("Rotation component", Transform3d(rotation), 3); - ImGui::SameLine(); - add_matrix("Scale component", Transform3d(scale), 3); - } - }; + auto add_matrix = [&imgui](const std::string& name, const Transform3d& m, unsigned int size) { + ImGui::BeginGroup(); + imgui.text(name); + if (ImGui::BeginTable(name.c_str(), size, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInner)) { + for (unsigned int r = 0; r < size; ++r) { + ImGui::TableNextRow(); + for (unsigned int c = 0; c < size; ++c) { + ImGui::TableSetColumnIndex(c); + imgui.text(std::to_string(m(r, c))); + } + } + ImGui::EndTable(); + } + ImGui::EndGroup(); + }; - add_matrices_set("World", v.world_matrix(), current_method_idx); - add_matrices_set("Instance", v.get_instance_transformation().get_matrix(), current_method_idx); - add_matrices_set("Volume", v.get_volume_transformation().get_matrix(), current_method_idx); + auto add_matrices_set = [add_matrix](const std::string& name, const Transform3d& m, size_t method) { + static unsigned int counter = 0; + ++counter; + if (ImGui::CollapsingHeader(name.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) { + add_matrix("Full", m, 4); - imgui.end(); + Matrix3d rotation; + Matrix3d scale; + if (method == 0) + m.computeRotationScaling(&rotation, &scale); + else + m.computeScalingRotation(&scale, &rotation); + + ImGui::SameLine(); + add_matrix("Rotation component", Transform3d(rotation), 3); + ImGui::SameLine(); + add_matrix("Scale component", Transform3d(scale), 3); + } + }; + + add_matrices_set("World", v.world_matrix(), current_method_idx); + add_matrices_set("Instance", v.get_instance_transformation().get_matrix(), current_method_idx); + add_matrices_set("Volume", v.get_volume_transformation().get_matrix(), current_method_idx); + + imgui.end(); } #endif // ENABLE_WORLD_COORDINATE_DEBUG diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index d2c483c6e..36f973839 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -242,6 +242,9 @@ private: // Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied. // Modifiers are taken in account std::optional m_full_unscaled_instance_local_bounding_box; + // Bounding box aligned to the axis of the currently selected reference system (World/Object/Part) + // and transform to place and orient it in world coordinates + std::optional> m_bounding_box_in_current_reference_system; #endif // ENABLE_WORLD_COORDINATE #if ENABLE_RENDER_SELECTION_CENTER @@ -385,10 +388,15 @@ public: // Bounding box of a single full instance selection, in world coordinates. // Modifiers are taken in account const BoundingBoxf3& get_full_scaled_instance_bounding_box() const; - // Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied. // Modifiers are taken in account const BoundingBoxf3& get_full_unscaled_instance_local_bounding_box() const; + // Returns the bounding box aligned to the axes of the currently selected reference system (World/Object/Part) + // and the transform to place and orient it in world coordinates + const std::pair& get_bounding_box_in_current_reference_system() const; + // Returns the bounding box aligned to the axes of the given reference system + // and the transform to place and orient it in world coordinates + std::pair get_bounding_box_in_reference_system(ECoordinatesType type) const; #endif // ENABLE_WORLD_COORDINATE void setup_cache(); @@ -464,7 +472,8 @@ private: m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); m_full_unscaled_instance_bounding_box.reset(); m_full_scaled_instance_bounding_box.reset(); - m_full_unscaled_instance_local_bounding_box.reset();; + m_full_unscaled_instance_local_bounding_box.reset(); + m_bounding_box_in_current_reference_system.reset(); } #else void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); } diff --git a/src/slic3r/GUI/SendSystemInfoDialog.cpp b/src/slic3r/GUI/SendSystemInfoDialog.cpp index dfb442d18..ffa147478 100644 --- a/src/slic3r/GUI/SendSystemInfoDialog.cpp +++ b/src/slic3r/GUI/SendSystemInfoDialog.cpp @@ -658,7 +658,7 @@ SendSystemInfoDialog::SendSystemInfoDialog(wxWindow* parent) wxString message; bool success = send_info(message); if (! message.IsEmpty()) - InfoDialog(nullptr, wxEmptyString, message).ShowModal(); + InfoDialog(this, wxEmptyString, message).ShowModal(); if (success) { save_version(); EndModal(0); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index cf3b96d80..796ce622b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2373,7 +2373,7 @@ void TabPrinter::build_fff() option = optgroup->get_option("start_gcode"); option.opt.full_width = true; option.opt.is_code = true; - option.opt.height = gcode_field_height;//150; + option.opt.height = 3 * gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("End G-code"), 0); @@ -2383,7 +2383,7 @@ void TabPrinter::build_fff() option = optgroup->get_option("end_gcode"); option.opt.full_width = true; option.opt.is_code = true; - option.opt.height = gcode_field_height;//150; + option.opt.height = 1.75 * gcode_field_height;//150; optgroup->append_single_option_line(option); optgroup = page->new_optgroup(L("Before layer change G-code"), 0); diff --git a/tests/libslic3r/test_arachne.cpp b/tests/libslic3r/test_arachne.cpp index e952695e9..2334fbc62 100644 --- a/tests/libslic3r/test_arachne.cpp +++ b/tests/libslic3r/test_arachne.cpp @@ -414,3 +414,40 @@ TEST_CASE("Arachne - #8597 - removeSmallAreas", "[ArachneRemoveSmallAreas8597]") REQUIRE(perimeters.size() == 1); } + +// Test case for missing infill that is probably caused by PolylineStitcher, which produced an open polyline. +TEST_CASE("Arachne - Missing infill", "[ArachneMissingInfill]") { + const Polygon poly_0 = { + Point( 5525881, 3649657), + Point( 452351, -2035297), + Point(-1014702, -2144286), + Point(-5142096, -9101108), + Point( 5525882, -9101108), + }; + + const Polygon poly_1 = { + Point(1415524, -2217520), + Point(1854189, -2113857), + Point(1566974, -2408538), + }; + + const Polygon poly_2 = { + Point(-42854, -3771357), + Point(310500, -3783332), + Point( 77735, -4059215), + }; + + Polygons polygons = {poly_0, poly_1, poly_2}; + coord_t spacing = 357079; + coord_t inset_count = 2; + + Arachne::WallToolPaths wallToolPaths(polygons, spacing, spacing, inset_count, 0, 0.2, PrintObjectConfig::defaults(), PrintConfig::defaults()); + wallToolPaths.generate(); + std::vector perimeters = wallToolPaths.getToolPaths(); + +#ifdef ARACHNE_DEBUG_OUT + export_perimeters_to_svg(debug_out_path("arachne-missing-infill.svg"), polygons, perimeters, union_ex(wallToolPaths.getInnerContour())); +#endif + +// REQUIRE(wallToolPaths.getInnerContour().size() == 1); +}