From 0a0219961b8b96fadbcf780b8756347573ff2c9f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 28 Feb 2020 14:59:59 +0100 Subject: Free rotating camera reworked to rotate around the free rotation axis in a single step. --- src/slic3r/GUI/Camera.cpp | 16 +++++++++------- src/slic3r/GUI/GLCanvas3D.cpp | 9 ++++----- src/slic3r/GUI/Mouse3DController.cpp | 4 ++-- 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'src/slic3r/GUI') diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index df3d219b2..3f0e6b891 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -326,15 +326,17 @@ void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, b m_view_matrix.fromPositionOrientationScale(m_view_rotation * (- m_target) + translation, m_view_rotation, Vec3d(1., 1., 1.)); } +// Virtual trackball, rotate around an axis, where the eucledian norm of the axis gives the rotation angle in radians. void Camera::rotate_local_around_target(const Vec3d& rotation_rad) { - Vec3d translation = m_view_matrix.translation() + m_view_rotation * m_target; - auto rot_z = Eigen::AngleAxisd(rotation_rad(2), get_dir_forward()); - auto rot_y = Eigen::AngleAxisd(rotation_rad(1), rot_z.inverse() * get_dir_up()); - auto rot_x = Eigen::AngleAxisd(rotation_rad(0), rot_y.inverse() * get_dir_right()); - m_view_rotation *= rot_z * rot_y * rot_x; - m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-m_target) + translation, m_view_rotation, Vec3d(1., 1., 1.)); - update_zenit(); + double angle = rotation_rad.norm(); + if (std::abs(angle) > EPSILON) { + Vec3d translation = m_view_matrix.translation() + m_view_rotation * m_target; + Vec3d axis = m_view_rotation.conjugate() * rotation_rad.normalized(); + m_view_rotation *= Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis)); + m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-m_target) + translation, m_view_rotation, Vec3d(1., 1., 1.)); + update_zenit(); + } } double Camera::min_zoom() const diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1ccebbabb..a6eee73e8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3464,13 +3464,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // if dragging over blank area with left button, rotate if (m_hover_volume_idxs.empty() && m_mouse.is_start_position_3D_defined()) { - const Vec3d& orig = m_mouse.drag.start_position_3D; - double x = Geometry::deg2rad(pos(0) - orig(0)) * (double)TRACKBALLSIZE; - double y = Geometry::deg2rad(pos(1) - orig(1)) * (double)TRACKBALLSIZE; + const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.); if (wxGetApp().plater()->get_mouse3d_controller().is_running() || (wxGetApp().app_config->get("use_free_camera") == "1")) - m_camera.rotate_local_around_target(Vec3d(y, x, 0.0)); + // Virtual track ball (similar to the 3DConnexion mouse). + m_camera.rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.)); else - m_camera.rotate_on_sphere(x, y, wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA); + m_camera.rotate_on_sphere(rot.x(), rot.y(), wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA); m_dirty = true; } diff --git a/src/slic3r/GUI/Mouse3DController.cpp b/src/slic3r/GUI/Mouse3DController.cpp index 2be017e54..c92557417 100644 --- a/src/slic3r/GUI/Mouse3DController.cpp +++ b/src/slic3r/GUI/Mouse3DController.cpp @@ -162,8 +162,8 @@ bool Mouse3DController::State::apply(Camera& camera) if (has_rotation()) { - Vec3d rotation = (m_rotation_params.scale * m_rotation.queue.front()).cast(); - camera.rotate_local_around_target(Vec3d(Geometry::deg2rad(rotation(0)), Geometry::deg2rad(-rotation(2)), Geometry::deg2rad(-rotation(1)))); + Vec3d rot = (m_rotation_params.scale * m_rotation.queue.front()).cast() * (PI / 180.); + camera.rotate_local_around_target(Vec3d(rot.x(), - rot.z(), rot.y())); m_rotation.queue.pop(); ret = true; } -- cgit v1.2.3