diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 94ab20696..e502b25d7 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -884,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 } { @@ -892,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(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index dc0b9fed7..5651ac190 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] 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/Selection.cpp b/src/slic3r/GUI/Selection.cpp index dd8364c02..461a00979 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -817,113 +817,117 @@ const std::pair& Selection::get_bounding_box_in_curr if (!m_bounding_box_in_current_reference_system.has_value()) { last_coordinates_type = int(coordinates_type); - - BoundingBoxf3 original_box; - Transform3d trafo; - - // - // calculate box aligned to current reference system - // - switch (coordinates_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()); - 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])); - *const_cast>*>(&m_bounding_box_in_current_reference_system) = { out_box, out_trafo.get_matrix_no_scaling_factor() }; + *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()); + 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() diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 67b28ac78..36f973839 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -391,9 +391,12 @@ public: // 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 axis of the currently selected reference system (World/Object/Part) + // 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();