1 #ifndef slic3r_Camera_hpp_ 2 #define slic3r_Camera_hpp_ 3 4 #include "libslic3r/BoundingBox.hpp" 5 #include "3DScene.hpp" 6 #include <array> 7 8 namespace Slic3r { 9 namespace GUI { 10 11 struct Camera 12 { 13 static const double DefaultDistance; 14 static const double DefaultZoomToBoxMarginFactor; 15 static const double DefaultZoomToVolumesMarginFactor; 16 static double FrustrumMinZRange; 17 static double FrustrumMinNearZ; 18 static double FrustrumZMargin; 19 static double MaxFovDeg; 20 21 enum EType : unsigned char 22 { 23 Unknown, 24 Ortho, 25 Perspective, 26 Num_types 27 }; 28 29 bool requires_zoom_to_bed; 30 31 private: 32 EType m_type{ Perspective }; 33 bool m_update_config_on_type_change_enabled{ false }; 34 Vec3d m_target{ Vec3d::Zero() }; 35 float m_zenit{ 45.0f }; 36 double m_zoom{ 1.0 }; 37 // Distance between camera position and camera target measured along the camera Z axis 38 mutable double m_distance{ DefaultDistance }; 39 mutable double m_gui_scale{ 1.0 }; 40 41 mutable std::array<int, 4> m_viewport; 42 mutable Transform3d m_view_matrix{ Transform3d::Identity() }; 43 // We are calculating the rotation part of the m_view_matrix from m_view_rotation. 44 mutable Eigen::Quaterniond m_view_rotation{ 1.0, 0.0, 0.0, 0.0 }; 45 mutable Transform3d m_projection_matrix{ Transform3d::Identity() }; 46 mutable std::pair<double, double> m_frustrum_zs; 47 48 BoundingBoxf3 m_scene_box; 49 50 public: 51 Camera(); 52 get_typeSlic3r::GUI::Camera53 EType get_type() const { return m_type; } 54 std::string get_type_as_string() const; 55 void set_type(EType type); 56 // valid values for type: "0" -> ortho, "1" -> perspective 57 void set_type(const std::string& type); 58 void select_next_type(); 59 enable_update_config_on_type_changeSlic3r::GUI::Camera60 void enable_update_config_on_type_change(bool enable) { m_update_config_on_type_change_enabled = enable; } 61 get_targetSlic3r::GUI::Camera62 const Vec3d& get_target() const { return m_target; } 63 void set_target(const Vec3d& target); 64 get_distanceSlic3r::GUI::Camera65 double get_distance() const { return (get_position() - m_target).norm(); } get_gui_scaleSlic3r::GUI::Camera66 double get_gui_scale() const { return m_gui_scale; } 67 get_zoomSlic3r::GUI::Camera68 double get_zoom() const { return m_zoom; } get_inv_zoomSlic3r::GUI::Camera69 double get_inv_zoom() const { assert(m_zoom != 0.0); return 1.0 / m_zoom; } 70 void update_zoom(double delta_zoom); 71 void set_zoom(double zoom); 72 get_scene_boxSlic3r::GUI::Camera73 const BoundingBoxf3& get_scene_box() const { return m_scene_box; } set_scene_boxSlic3r::GUI::Camera74 void set_scene_box(const BoundingBoxf3& box) { m_scene_box = box; } 75 76 void select_view(const std::string& direction); 77 get_viewportSlic3r::GUI::Camera78 const std::array<int, 4>& get_viewport() const { return m_viewport; } get_view_matrixSlic3r::GUI::Camera79 const Transform3d& get_view_matrix() const { return m_view_matrix; } get_projection_matrixSlic3r::GUI::Camera80 const Transform3d& get_projection_matrix() const { return m_projection_matrix; } 81 get_dir_rightSlic3r::GUI::Camera82 Vec3d get_dir_right() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(0); } get_dir_upSlic3r::GUI::Camera83 Vec3d get_dir_up() const { return m_view_matrix.matrix().block(0, 0, 3, 3).row(1); } get_dir_forwardSlic3r::GUI::Camera84 Vec3d get_dir_forward() const { return -m_view_matrix.matrix().block(0, 0, 3, 3).row(2); } 85 get_positionSlic3r::GUI::Camera86 Vec3d get_position() const { return m_view_matrix.matrix().inverse().block(0, 3, 3, 1); } 87 get_near_zSlic3r::GUI::Camera88 double get_near_z() const { return m_frustrum_zs.first; } get_far_zSlic3r::GUI::Camera89 double get_far_z() const { return m_frustrum_zs.second; } get_z_rangeSlic3r::GUI::Camera90 const std::pair<double, double>& get_z_range() const { return m_frustrum_zs; } 91 92 double get_fov() const; 93 94 void apply_viewport(int x, int y, unsigned int w, unsigned int h) const; 95 void apply_view_matrix() const; 96 // Calculates and applies the projection matrix tighting the frustrum z range around the given box. 97 // If larger z span is needed, pass the desired values of near and far z (negative values are ignored) 98 void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0) const; 99 100 void zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultZoomToBoxMarginFactor); 101 void zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor = DefaultZoomToVolumesMarginFactor); 102 103 #if ENABLE_CAMERA_STATISTICS 104 void debug_render() const; 105 #endif // ENABLE_CAMERA_STATISTICS 106 107 // translate the camera in world space translate_worldSlic3r::GUI::Camera108 void translate_world(const Vec3d& displacement) { this->set_target(m_target + displacement); } 109 110 // rotate the camera on a sphere having center == m_target and radius == m_distance 111 // using the given variations of spherical coordinates 112 // if apply_limits == true the camera stops rotating when its forward vector is parallel to the world Z axis 113 void rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad, bool apply_limits); 114 115 // rotate the camera around three axes parallel to the camera local axes and passing through m_target 116 void rotate_local_around_target(const Vec3d& rotation_rad); 117 118 // returns true if the camera z axis (forward) is pointing in the negative direction of the world z axis is_looking_downwardSlic3r::GUI::Camera119 bool is_looking_downward() const { return get_dir_forward().dot(Vec3d::UnitZ()) < 0.0; } 120 121 // forces camera right vector to be parallel to XY plane recover_from_free_cameraSlic3r::GUI::Camera122 void recover_from_free_camera() 123 { 124 if (std::abs(get_dir_right()(2)) > EPSILON) 125 look_at(get_position(), m_target, Vec3d::UnitZ()); 126 } 127 128 void look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up); 129 max_zoomSlic3r::GUI::Camera130 double max_zoom() const { return 250.0; } 131 double min_zoom() const; 132 133 private: 134 // returns tight values for nearZ and farZ plane around the given bounding box 135 // the camera MUST be outside of the bounding box in eye coordinate of the given box 136 std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const; 137 double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, double margin_factor = DefaultZoomToBoxMarginFactor) const; 138 double calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, Vec3d& center, double margin_factor = DefaultZoomToVolumesMarginFactor) const; 139 void set_distance(double distance) const; 140 141 void set_default_orientation(); 142 Vec3d validate_target(const Vec3d& target) const; 143 void update_zenit(); 144 }; 145 146 } // GUI 147 } // Slic3r 148 149 #endif // slic3r_Camera_hpp_ 150 151