diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 4aa5ab32f..50c93d72c 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -20,90 +20,91 @@ static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f namespace Slic3r { namespace GUI { - // returns the intersection of the given ray with the plane parallel to plane XY and passing through the given center - // coordinates are local to the plane - Vec3d intersection_on_plane_xy(const Linef3& ray, const Vec3d& center) +// returns the intersection of the given ray with the plane parallel to plane XY and passing through the given center +// coordinates are local to the plane +Vec3d intersection_on_plane_xy(const Linef3& ray, const Vec3d& center) +{ + Transform3d m = Transform3d::Identity(); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + return Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0); +} + +// returns the intersection of the given ray with the plane parallel to plane XZ and passing through the given center +// coordinates are local to the plane +Vec3d intersection_on_plane_xz(const Linef3& ray, const Vec3d& center) +{ + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + return Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1)); +} + +// returns the intersection of the given ray with the plane parallel to plane YZ and passing through the given center +// coordinates are local to the plane +Vec3d intersection_on_plane_yz(const Linef3& ray, const Vec3d& center) +{ + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + + return Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0)); +} + +// return an index: +// 0 for plane XY +// 1 for plane XZ +// 2 for plane YZ +// which indicates which plane is best suited for intersecting the given unit vector +// giving precedence to the plane with the given index +unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_plane) +{ + unsigned int ret = preferred_plane; + + // 1st checks if the given vector is not parallel to the given preferred plane + double dot_to_normal = 0.0; + switch (ret) { - Transform3d m = Transform3d::Identity(); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); - return Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0); + case 0: // plane xy + { + dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitZ())); + break; + } + case 1: // plane xz + { + dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY())); + break; + } + case 2: // plane yz + { + dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX())); + break; + } + default: + { + break; + } } - // returns the intersection of the given ray with the plane parallel to plane XZ and passing through the given center - // coordinates are local to the plane - Vec3d intersection_on_plane_xz(const Linef3& ray, const Vec3d& center) + // if almost parallel, select the plane whose normal direction is closest to the given vector direction, + // otherwise return the given preferred plane index + if (dot_to_normal < 0.1) { - Transform3d m = Transform3d::Identity(); - m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX())); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); - return Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1)); + typedef std::map ProjsMap; + ProjsMap projs_map; + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitZ())), 0)); // plane xy + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(-Vec3d::UnitY())), 1)); // plane xz + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitX())), 2)); // plane yz + ret = projs_map.rbegin()->second; } - // returns the intersection of the given ray with the plane parallel to plane YZ and passing through the given center - // coordinates are local to the plane - Vec3d intersection_on_plane_yz(const Linef3& ray, const Vec3d& center) - { - Transform3d m = Transform3d::Identity(); - m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY())); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); - - return Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0)); - } - - // return an index: - // 0 for plane XY - // 1 for plane XZ - // 2 for plane YZ - // which indicates which plane is best suited for intersecting the given unit vector - // giving precedence to the plane with the given index - unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_plane) - { - unsigned int ret = preferred_plane; - - // 1st checks if the given vector is not parallel to the given preferred plane - double dot_to_normal = 0.0; - switch (ret) - { - case 0: // plane xy - { - dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitZ())); - break; - } - case 1: // plane xz - { - dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY())); - break; - } - case 2: // plane yz - { - dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX())); - break; - } - default: - { - break; - } - } - - // if almost parallel, select the plane whose normal direction is closest to the given vector direction, - // otherwise return the given preferred plane index - if (dot_to_normal < 0.1) - { - typedef std::map ProjsMap; - ProjsMap projs_map; - projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitZ())), 0)); // plane xy - projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(-Vec3d::UnitY())), 1)); // plane xz - projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitX())), 2)); // plane yz - ret = projs_map.rbegin()->second; - } - - return ret; - } + return ret; +} - const float GLGizmoBase::Grabber::HalfSize = 2.0f; +const float GLGizmoBase::Grabber::SizeFactor = 0.025f; +const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; GLGizmoBase::Grabber::Grabber() @@ -117,7 +118,7 @@ GLGizmoBase::Grabber::Grabber() color[2] = 1.0f; } -void GLGizmoBase::Grabber::render(bool hover) const +void GLGizmoBase::Grabber::render(bool hover, const BoundingBoxf3& box) const { float render_color[3]; if (hover) @@ -129,12 +130,15 @@ void GLGizmoBase::Grabber::render(bool hover) const else ::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float)); - render(render_color, true); + render(box, render_color, true); } -void GLGizmoBase::Grabber::render(const float* render_color, bool use_lighting) const +void GLGizmoBase::Grabber::render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const { - float half_size = dragging ? HalfSize * DraggingScaleFactor : HalfSize; + float max_size = (float)box.max_size(); + float half_size = dragging ? max_size * SizeFactor * DraggingScaleFactor : max_size * SizeFactor; + half_size = std::max(half_size, MinHalfSize); + if (use_lighting) ::glEnable(GL_LIGHTING); @@ -291,16 +295,16 @@ float GLGizmoBase::picking_color_component(unsigned int id) const return (float)color / 255.0f; } -void GLGizmoBase::render_grabbers() const +void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const { for (int i = 0; i < (int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) - m_grabbers[i].render(m_hover_id == i); + m_grabbers[i].render((m_hover_id == i), box); } } -void GLGizmoBase::render_grabbers_for_picking() const +void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { @@ -309,7 +313,7 @@ void GLGizmoBase::render_grabbers_for_picking() const m_grabbers[i].color[0] = 1.0f; m_grabbers[i].color[1] = 1.0f; m_grabbers[i].color[2] = picking_color_component(i); - m_grabbers[i].render_for_picking(); + m_grabbers[i].render_for_picking(box); } } } @@ -440,7 +444,7 @@ void GLGizmoRotate::on_render(const BoundingBoxf3& box) const if (m_hover_id != -1) render_angle(); - render_grabber(); + render_grabber(box); ::glPopMatrix(); } @@ -452,7 +456,7 @@ void GLGizmoRotate::on_render_for_picking(const BoundingBoxf3& box) const ::glPushMatrix(); transform_to_local(); - render_grabbers_for_picking(); + render_grabbers_for_picking(box); ::glPopMatrix(); } @@ -544,7 +548,7 @@ void GLGizmoRotate::render_angle() const ::glEnd(); } -void GLGizmoRotate::render_grabber() const +void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const { double grabber_radius = (double)(m_radius + GrabberOffset); m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); @@ -558,7 +562,7 @@ void GLGizmoRotate::render_grabber() const ::glEnd(); ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); - render_grabbers(); + render_grabbers(box); } void GLGizmoRotate::transform_to_local() const @@ -829,7 +833,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const render_grabbers_connection(4, 5); } // draw grabbers - render_grabbers(); + render_grabbers(m_box); } else if ((m_hover_id == 0) || (m_hover_id == 1)) { @@ -846,8 +850,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[0].color); render_grabbers_connection(0, 1); // draw grabbers - m_grabbers[0].render(true); - m_grabbers[1].render(true); + m_grabbers[0].render(true, m_box); + m_grabbers[1].render(true, m_box); } else if ((m_hover_id == 2) || (m_hover_id == 3)) { @@ -864,8 +868,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[2].color); render_grabbers_connection(2, 3); // draw grabbers - m_grabbers[2].render(true); - m_grabbers[3].render(true); + m_grabbers[2].render(true, m_box); + m_grabbers[3].render(true, m_box); } else if ((m_hover_id == 4) || (m_hover_id == 5)) { @@ -882,8 +886,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[4].color); render_grabbers_connection(4, 5); // draw grabbers - m_grabbers[4].render(true); - m_grabbers[5].render(true); + m_grabbers[4].render(true, m_box); + m_grabbers[5].render(true, m_box); } else if (m_hover_id >= 6) { @@ -899,7 +903,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // draw grabbers for (int i = 6; i < 10; ++i) { - m_grabbers[i].render(true); + m_grabbers[i].render(true, m_box); } } } @@ -908,7 +912,7 @@ void GLGizmoScale3D::on_render_for_picking(const BoundingBoxf3& box) const { ::glDisable(GL_DEPTH_TEST); - render_grabbers_for_picking(); + render_grabbers_for_picking(box); } void GLGizmoScale3D::render_box(const BoundingBoxf3& box) const @@ -1118,7 +1122,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const } // draw grabbers - render_grabbers(); + render_grabbers(box); } else { @@ -1130,7 +1134,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const ::glEnd(); // draw grabber - m_grabbers[m_hover_id].render(true); + m_grabbers[m_hover_id].render(true, box); } } @@ -1138,7 +1142,7 @@ void GLGizmoMove3D::on_render_for_picking(const BoundingBoxf3& box) const { ::glDisable(GL_DEPTH_TEST); - render_grabbers_for_picking(); + render_grabbers_for_picking(box); } double GLGizmoMove3D::calc_displacement(unsigned int preferred_plane_id, const Linef3& mouse_ray) const diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 8760b1c7d..d3cad05c6 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -22,7 +22,8 @@ class GLGizmoBase protected: struct Grabber { - static const float HalfSize; + static const float SizeFactor; + static const float MinHalfSize; static const float DraggingScaleFactor; Vec3d center; @@ -33,11 +34,11 @@ protected: Grabber(); - void render(bool hover) const; - void render_for_picking() const { render(color, false); } + void render(bool hover, const BoundingBoxf3& box) const; + void render_for_picking(const BoundingBoxf3& box) const { render(box, color, false); } private: - void render(const float* render_color, bool use_lighting) const; + void render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const; void render_face(float half_size) const; }; @@ -109,8 +110,8 @@ protected: virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0; float picking_color_component(unsigned int id) const; - void render_grabbers() const; - void render_grabbers_for_picking() const; + void render_grabbers(const BoundingBoxf3& box) const; + void render_grabbers_for_picking(const BoundingBoxf3& box) const; void set_tooltip(const std::string& tooltip) const; std::string format(float value, unsigned int decimals) const; @@ -163,7 +164,7 @@ private: void render_snap_radii() const; void render_reference_radius() const; void render_angle() const; - void render_grabber() const; + void render_grabber(const BoundingBoxf3& box) const; void transform_to_local() const; // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate