From a393df59d74dc252e8e977afa2c35875b2fcf02e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 16 Apr 2021 14:05:55 +0200 Subject: [PATCH] Further refactoring into struct Camera --- src/slic3r/GUI/Camera.cpp | 156 ++++++++++++++++---------------------- src/slic3r/GUI/Camera.hpp | 10 +-- 2 files changed, 69 insertions(+), 97 deletions(-) diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 82522b7a3..d8b80f1ce 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -21,12 +21,6 @@ double Camera::FrustrumMinNearZ = 100.0; double Camera::FrustrumZMargin = 10.0; double Camera::MaxFovDeg = 60.0; -Camera::Camera() - : requires_zoom_to_bed(false) -{ - set_default_orientation(); -} - std::string Camera::get_type_as_string() const { switch (m_type) @@ -49,11 +43,6 @@ void Camera::set_type(EType type) } } -void Camera::set_type(const std::string& type) -{ - set_type((type == "1") ? Perspective : Ortho); -} - void Camera::select_next_type() { unsigned char next = (unsigned char)m_type + 1; @@ -65,24 +54,18 @@ void Camera::select_next_type() void Camera::set_target(const Vec3d& target) { - Vec3d new_target = validate_target(target); - Vec3d new_displacement = new_target - m_target; - if (!new_displacement.isApprox(Vec3d::Zero())) - { + const Vec3d new_target = validate_target(target); + const Vec3d new_displacement = new_target - m_target; + if (!new_displacement.isApprox(Vec3d::Zero())) { m_target = new_target; m_view_matrix.translate(-new_displacement); } } -void Camera::update_zoom(double delta_zoom) -{ - set_zoom(m_zoom / (1.0 - std::max(std::min(delta_zoom, 4.0), -4.0) * 0.1)); -} - void Camera::set_zoom(double zoom) { // Don't allow to zoom too far outside the scene. - double zoom_min = min_zoom(); + const double zoom_min = min_zoom(); if (zoom_min > 0.0) zoom = std::max(zoom, zoom_min); @@ -138,7 +121,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa double w = 0.0; double h = 0.0; - double old_distance = m_distance; + const double old_distance = m_distance; std::pair* frustrum_zs = const_cast*>(&m_frustrum_zs); *frustrum_zs = calc_tight_frustrum_zs_around(box); if (m_distance != old_distance) @@ -154,7 +137,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa w = 0.5 * (double)m_viewport[2]; h = 0.5 * (double)m_viewport[3]; - double inv_zoom = get_inv_zoom(); + const double inv_zoom = get_inv_zoom(); w *= inv_zoom; h *= inv_zoom; @@ -169,7 +152,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa case Perspective: { // scale near plane to keep w and h constant on the plane at z = m_distance - double scale = frustrum_zs->first / m_distance; + const double scale = frustrum_zs->first / m_distance; w *= scale; h *= scale; *const_cast(&m_gui_scale) = scale; @@ -202,7 +185,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor) { // Calculate the zoom factor needed to adjust the view around the given box. - double zoom = calc_zoom_to_bounding_box_factor(box, margin_factor); + const double zoom = calc_zoom_to_bounding_box_factor(box, margin_factor); if (zoom > 0.0) { m_zoom = zoom; // center view around box center @@ -213,9 +196,8 @@ void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor) void Camera::zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor) { Vec3d center; - double zoom = calc_zoom_to_volumes_factor(volumes, center, margin_factor); - if (zoom > 0.0) - { + const double zoom = calc_zoom_to_volumes_factor(volumes, center, margin_factor); + if (zoom > 0.0) { m_zoom = zoom; // center view around the calculated center set_target(center); @@ -289,8 +271,8 @@ void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, b } } - Vec3d translation = m_view_matrix.translation() + m_view_rotation * m_target; - auto rot_z = Eigen::AngleAxisd(delta_azimut_rad, Vec3d::UnitZ()); + const Vec3d translation = m_view_matrix.translation() + m_view_rotation * m_target; + const auto rot_z = Eigen::AngleAxisd(delta_azimut_rad, Vec3d::UnitZ()); m_view_rotation *= rot_z * Eigen::AngleAxisd(delta_zenit_rad, rot_z.inverse() * get_dir_right()); m_view_rotation.normalize(); m_view_matrix.fromPositionOrientationScale(m_view_rotation * (- m_target) + translation, m_view_rotation, Vec3d(1., 1., 1.)); @@ -299,10 +281,10 @@ void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, b // 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) { - double angle = rotation_rad.norm(); + const 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(); + const Vec3d translation = m_view_matrix.translation() + m_view_rotation * m_target; + const Vec3d axis = m_view_rotation.conjugate() * rotation_rad.normalized(); m_view_rotation *= Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis)); m_view_rotation.normalize(); m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-m_target) + translation, m_view_rotation, Vec3d(1., 1., 1.)); @@ -310,18 +292,13 @@ void Camera::rotate_local_around_target(const Vec3d& rotation_rad) } } -double Camera::min_zoom() const -{ - return 0.7 * calc_zoom_to_bounding_box_factor(m_scene_box); -} - std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const { std::pair ret; auto& [near_z, far_z] = ret; // box in eye space - BoundingBoxf3 eye_box = box.transformed(m_view_matrix); + const BoundingBoxf3 eye_box = box.transformed(m_view_matrix); near_z = -eye_box.max(2); far_z = -eye_box.min(2); @@ -331,14 +308,14 @@ std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBo // ensure min size if (far_z - near_z < FrustrumMinZRange) { - double mid_z = 0.5 * (near_z + far_z); - double half_size = 0.5 * FrustrumMinZRange; + const double mid_z = 0.5 * (near_z + far_z); + const double half_size = 0.5 * FrustrumMinZRange; near_z = mid_z - half_size; far_z = mid_z + half_size; } if (near_z < FrustrumMinNearZ) { - double delta = FrustrumMinNearZ - near_z; + const double delta = FrustrumMinNearZ - near_z; set_distance(m_distance + delta); near_z += delta; far_z += delta; @@ -358,45 +335,43 @@ std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBo double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, double margin_factor) const { - double max_bb_size = box.max_size(); + const double max_bb_size = box.max_size(); if (max_bb_size == 0.0) return -1.0; // project the box vertices on a plane perpendicular to the camera forward axis // then calculates the vertices coordinate on this plane along the camera xy axes - Vec3d right = get_dir_right(); - Vec3d up = get_dir_up(); - Vec3d forward = get_dir_forward(); - - Vec3d bb_center = box.center(); + const Vec3d right = get_dir_right(); + const Vec3d up = get_dir_up(); + const Vec3d forward = get_dir_forward(); + const Vec3d bb_center = box.center(); // box vertices in world space - std::vector vertices; - vertices.reserve(8); - vertices.push_back(box.min); - vertices.emplace_back(box.max(0), box.min(1), box.min(2)); - vertices.emplace_back(box.max(0), box.max(1), box.min(2)); - vertices.emplace_back(box.min(0), box.max(1), box.min(2)); - vertices.emplace_back(box.min(0), box.min(1), box.max(2)); - vertices.emplace_back(box.max(0), box.min(1), box.max(2)); - vertices.push_back(box.max); - vertices.emplace_back(box.min(0), box.max(1), box.max(2)); + const std::vector vertices = { + box.min, + { box.max(0), box.min(1), box.min(2) }, + { box.max(0), box.max(1), box.min(2) }, + { box.min(0), box.max(1), box.min(2) }, + { box.min(0), box.min(1), box.max(2) }, + { box.max(0), box.min(1), box.max(2) }, + box.max, + { box.min(0), box.max(1), box.max(2) } + }; double min_x = DBL_MAX; double min_y = DBL_MAX; double max_x = -DBL_MAX; double max_y = -DBL_MAX; - for (const Vec3d& v : vertices) - { + for (const Vec3d& v : vertices) { // project vertex on the plane perpendicular to camera forward axis - Vec3d pos = v - bb_center; - Vec3d proj_on_plane = pos - pos.dot(forward) * forward; + const Vec3d pos = v - bb_center; + const Vec3d proj_on_plane = pos - pos.dot(forward) * forward; // calculates vertex coordinate along camera xy axes - double x_on_plane = proj_on_plane.dot(right); - double y_on_plane = proj_on_plane.dot(up); + const double x_on_plane = proj_on_plane.dot(right); + const double y_on_plane = proj_on_plane.dot(up); min_x = std::min(min_x, x_on_plane); min_y = std::min(min_y, y_on_plane); @@ -406,7 +381,7 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, double double dx = max_x - min_x; double dy = max_y - min_y; - if ((dx <= 0.0) || (dy <= 0.0)) + if (dx <= 0.0 || dy <= 0.0) return -1.0f; dx *= margin_factor; @@ -423,13 +398,12 @@ double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, Vec3d& c // project the volumes vertices on a plane perpendicular to the camera forward axis // then calculates the vertices coordinate on this plane along the camera xy axes - Vec3d right = get_dir_right(); - Vec3d up = get_dir_up(); - Vec3d forward = get_dir_forward(); + const Vec3d right = get_dir_right(); + const Vec3d up = get_dir_up(); + const Vec3d forward = get_dir_forward(); BoundingBoxf3 box; - for (const GLVolume* volume : volumes) - { + for (const GLVolume* volume : volumes) { box.merge(volume->transformed_bounding_box()); } center = box.center(); @@ -439,24 +413,22 @@ double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, Vec3d& c double max_x = -DBL_MAX; double max_y = -DBL_MAX; - for (const GLVolume* volume : volumes) - { + for (const GLVolume* volume : volumes) { const Transform3d& transform = volume->world_matrix(); const TriangleMesh* hull = volume->convex_hull(); if (hull == nullptr) continue; - for (const Vec3f& vertex : hull->its.vertices) - { - Vec3d v = transform * vertex.cast(); + for (const Vec3f& vertex : hull->its.vertices) { + const Vec3d v = transform * vertex.cast(); // project vertex on the plane perpendicular to camera forward axis - Vec3d pos = v - center; - Vec3d proj_on_plane = pos - pos.dot(forward) * forward; + const Vec3d pos = v - center; + const Vec3d proj_on_plane = pos - pos.dot(forward) * forward; // calculates vertex coordinate along camera xy axes - double x_on_plane = proj_on_plane.dot(right); - double y_on_plane = proj_on_plane.dot(up); + const double x_on_plane = proj_on_plane.dot(right); + const double y_on_plane = proj_on_plane.dot(up); min_x = std::min(min_x, x_on_plane); min_y = std::min(min_y, y_on_plane); @@ -467,8 +439,8 @@ double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, Vec3d& c center += 0.5 * (max_x + min_x) * right + 0.5 * (max_y + min_y) * up; - double dx = margin_factor * (max_x - min_x); - double dy = margin_factor * (max_y - min_y); + const double dx = margin_factor * (max_x - min_x); + const double dy = margin_factor * (max_y - min_y); if (dx <= 0.0 || dy <= 0.0) return -1.0f; @@ -486,13 +458,13 @@ void Camera::set_distance(double distance) const void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up) { - Vec3d unit_z = (position - target).normalized(); - Vec3d unit_x = up.cross(unit_z).normalized(); - Vec3d unit_y = unit_z.cross(unit_x).normalized(); + const Vec3d unit_z = (position - target).normalized(); + const Vec3d unit_x = up.cross(unit_z).normalized(); + const Vec3d unit_y = unit_z.cross(unit_x).normalized(); m_target = target; m_distance = (position - target).norm(); - Vec3d new_position = m_target + m_distance * unit_z; + const Vec3d new_position = m_target + m_distance * unit_z; m_view_matrix(0, 0) = unit_x(0); m_view_matrix(0, 1) = unit_x(1); @@ -524,10 +496,10 @@ void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up void Camera::set_default_orientation() { 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)); + const double theta_rad = Geometry::deg2rad(-(double)m_zenit); + const double phi_rad = Geometry::deg2rad(45.0); + const double sin_theta = ::sin(theta_rad); + const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad)); m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ()); m_view_rotation.normalize(); m_view_matrix.fromPositionOrientationScale(m_view_rotation * (- camera_pos), m_view_rotation, Vec3d(1., 1., 1.)); @@ -542,9 +514,9 @@ Vec3d Camera::validate_target(const Vec3d& target) const test_box.scale(ScaleFactor); test_box.translate(m_scene_box.center()); - return Vec3d(std::clamp(target(0), test_box.min(0), test_box.max(0)), - std::clamp(target(1), test_box.min(1), test_box.max(1)), - std::clamp(target(2), test_box.min(2), test_box.max(2))); + return { std::clamp(target(0), test_box.min(0), test_box.max(0)), + 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() diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 574a6eed7..1abb430ca 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -26,7 +26,7 @@ struct Camera Num_types }; - bool requires_zoom_to_bed; + bool requires_zoom_to_bed{ false }; private: EType m_type{ Perspective }; @@ -48,13 +48,13 @@ private: BoundingBoxf3 m_scene_box; public: - Camera(); + Camera() { set_default_orientation(); } EType get_type() const { return m_type; } std::string get_type_as_string() const; void set_type(EType type); // valid values for type: "0" -> ortho, "1" -> perspective - void set_type(const std::string& type); + void set_type(const std::string& type) { set_type((type == "1") ? Perspective : Ortho); } void select_next_type(); void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; } @@ -67,7 +67,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); + 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 set_zoom(double zoom); const BoundingBoxf3& get_scene_box() const { return m_scene_box; } @@ -127,7 +127,7 @@ public: void look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up); double max_zoom() const { return 250.0; } - double min_zoom() const; + double min_zoom() const { return 0.7 * calc_zoom_to_bounding_box_factor(m_scene_box); } private: // returns tight values for nearZ and farZ plane around the given bounding box