diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index a4eccf050..18075c3f8 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -50,9 +50,11 @@ Camera::Camera() #endif // ENABLE_6DOF_CAMERA , m_type(Perspective) , m_target(Vec3d::Zero()) -#if !ENABLE_6DOF_CAMERA +#if ENABLE_6DOF_CAMERA + , m_zenit(45.0f) +#else , m_theta(45.0f) -#endif // !ENABLE_6DOF_CAMERA +#endif // ENABLE_6DOF_CAMERA , m_zoom(1.0) , m_distance(DefaultDistance) , m_gui_scale(1.0) @@ -409,6 +411,9 @@ void Camera::debug_render() const Vec3f position = get_position().cast(); Vec3f target = m_target.cast(); float distance = (float)get_distance(); +#if ENABLE_6DOF_CAMERA + float zenit = (float)m_zenit; +#endif // ENABLE_6DOF_CAMERA Vec3f forward = get_dir_forward().cast(); Vec3f right = get_dir_right().cast(); Vec3f up = get_dir_up().cast(); @@ -425,6 +430,10 @@ void Camera::debug_render() const ImGui::InputFloat3("Position", position.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); ImGui::InputFloat3("Target", target.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); ImGui::InputFloat("Distance", &distance, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags_ReadOnly); +#if ENABLE_6DOF_CAMERA + ImGui::Separator(); + ImGui::InputFloat("Zenit", &zenit, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags_ReadOnly); +#endif // ENABLE_6DOF_CAMERA ImGui::Separator(); ImGui::InputFloat3("Forward", forward.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); ImGui::InputFloat3("Right", right.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); @@ -456,8 +465,20 @@ void Camera::translate_world(const Vec3d& displacement) } } -void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad) +void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, bool apply_limits) { + m_zenit += Geometry::rad2deg(delta_zenit_rad); + if (apply_limits) { + if (m_zenit > 90.0f) { + delta_zenit_rad -= Geometry::deg2rad(m_zenit - 90.0f); + m_zenit = 90.0f; + } + else if (m_zenit < -90.0f) { + delta_zenit_rad -= Geometry::deg2rad(m_zenit + 90.0f); + m_zenit = -90.0f; + } + } + // FIXME -> The following is a HACK !!! // When the value of the zenit rotation is large enough, the following call to rotate() shows // numerical instability introducing some scaling into m_view_matrix (verified by checking @@ -501,6 +522,7 @@ void Camera::rotate_local_around_pivot(const Vec3d& rotation_rad, const Vec3d& p m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(1), get_dir_up())); m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(2), get_dir_forward())); translate_world(center); + update_zenit(); } #endif // ENABLE_6DOF_CAMERA @@ -770,11 +792,14 @@ void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up m_view_matrix(3, 1) = 0.0; m_view_matrix(3, 2) = 0.0; m_view_matrix(3, 3) = 1.0; + + update_zenit(); } void Camera::set_default_orientation() { - double theta_rad = Geometry::deg2rad(-45.0); + m_zenit = 45.0f; + double theta_rad = Geometry::deg2rad(-(double)m_zenit); double phi_rad = Geometry::deg2rad(45.0); double sin_theta = ::sin(theta_rad); Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad)); @@ -795,6 +820,11 @@ Vec3d Camera::validate_target(const Vec3d& target) const std::clamp(target(1), test_box.min(1), test_box.max(1)), std::clamp(target(2), test_box.min(2), test_box.max(2))); } + +void Camera::update_zenit() +{ + m_zenit = Geometry::rad2deg(0.5 * M_PI - std::acos(std::clamp(-get_dir_forward().dot(Vec3d::UnitZ()), -1.0, 1.0))); +} #endif // ENABLE_6DOF_CAMERA } // GUI diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index b0a646ebf..cda6b77b4 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -39,9 +39,11 @@ struct Camera private: EType m_type; Vec3d m_target; -#if !ENABLE_6DOF_CAMERA +#if ENABLE_6DOF_CAMERA + float m_zenit; +#else float m_theta; -#endif // !ENABLE_6DOF_CAMERA +#endif // ENABLE_6DOF_CAMERA double m_zoom; // Distance between camera position and camera target measured along the camera Z axis mutable double m_distance; @@ -136,7 +138,8 @@ public: // rotate the camera on a sphere having center == m_target and radius == m_distance // using the given variations of spherical coordinates - void rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad); + // if apply_limits == true the camera stops rotating when its forward vector is parallel to the world Z axis + void rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, bool apply_limits); // rotate the camera around three axes parallel to the camera local axes and passing through m_target void rotate_local_around_target(const Vec3d& rotation_rad); @@ -171,6 +174,7 @@ private: void look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up); void set_default_orientation(); Vec3d validate_target(const Vec3d& target) const; + void update_zenit(); #endif // ENABLE_6DOF_CAMERA }; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7c0db32c0..ac6071d3f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3499,7 +3499,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) 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)); else - m_camera.rotate_on_sphere(x, y); + m_camera.rotate_on_sphere(x, y, wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA); #else float sign = m_camera.inverted_phi ? -1.0f : 1.0f; m_camera.phi += sign * ((float)pos(0) - (float)orig(0)) * TRACKBALLSIZE;