diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index ca37795489..d95871c76b 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -20,6 +20,7 @@ double Camera::FrustrumMinZRange = 50.0; double Camera::FrustrumMinNearZ = 100.0; double Camera::FrustrumZMargin = 10.0; double Camera::MaxFovDeg = 60.0; +double Camera::ZoomUnit = 0.1; std::string Camera::get_type_as_string() const { @@ -52,6 +53,12 @@ void Camera::select_next_type() set_type((EType)next); } +void Camera::translate(const Vec3d& displacement) { + if (!displacement.isApprox(Vec3d::Zero())) { + m_view_matrix.translate(-displacement); + } +} + void Camera::set_target(const Vec3d& target) { //BBS do not check validation diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 99133ff572..3bc1385e89 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -22,6 +22,7 @@ struct Camera static double FrustrumMinNearZ; static double FrustrumZMargin; static double MaxFovDeg; + static double ZoomUnit; enum class EType : unsigned char { @@ -67,6 +68,7 @@ public: void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; } + void translate(const Vec3d& displacement); const Vec3d& get_target() const { return m_target; } void set_target(const Vec3d& target); @@ -76,7 +78,7 @@ public: double get_zoom() const { return m_zoom; } double get_inv_zoom() const { assert(m_zoom != 0.0); return 1.0 / m_zoom; } - void update_zoom(double delta_zoom) { set_zoom(m_zoom / (1.0 - std::max(std::min(delta_zoom, 4.0), -4.0) * 0.1)); } + void update_zoom(double delta_zoom) { set_zoom(m_zoom / (1.0 - std::max(std::min(delta_zoom, 4.0), -4.0) * ZoomUnit)); } void set_zoom(double zoom); const BoundingBoxf3& get_scene_box() const { return m_scene_box; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 469982ae75..fdeb870aae 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3585,7 +3585,21 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) #else double direction_factor = 1.0; #endif - _update_camera_zoom(direction_factor * (double)evt.GetWheelRotation() / (double)evt.GetWheelDelta()); + auto delta = direction_factor * (double)evt.GetWheelRotation() / (double)evt.GetWheelDelta(); + if (evt.CmdDown()) { + _update_camera_zoom(delta); + } + else { + auto cnv_size = get_canvas_size(); + auto screen_center_3d_pos = _mouse_to_3d({ cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 }); + auto mouse_3d_pos = _mouse_to_3d({evt.GetX(), evt.GetY()}); + Vec3d displacement = mouse_3d_pos - screen_center_3d_pos; + wxGetApp().plater()->get_camera().translate(displacement); + auto origin_zoom = wxGetApp().plater()->get_camera().get_zoom(); + _update_camera_zoom(delta); + auto new_zoom = wxGetApp().plater()->get_camera().get_zoom(); + wxGetApp().plater()->get_camera().translate((-displacement) / (new_zoom / origin_zoom)); + } } void GLCanvas3D::on_timer(wxTimerEvent& evt)