diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index e85be42ce3..38f5f5fdb4 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -626,7 +626,7 @@ Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) { const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); - const Vec3d axis = angle_axis.axis(); + const Vec3d& axis = angle_axis.axis(); const double angle = angle_axis.angle(); #ifndef NDEBUG if (std::abs(angle) > 1e-8) { diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 345eba3ee8..7f6c42bc05 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -74,17 +74,6 @@ #define ENABLE_SHOW_NON_MANIFOLD_EDGES (1 && ENABLE_2_5_0_ALPHA1) // Enable rework of Reload from disk command #define ENABLE_RELOAD_FROM_DISK_REWORK (1 && ENABLE_2_5_0_ALPHA1) -// Enable showing toolpaths center of gravity -#define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1) -// Enable recalculating toolpaths when switching to/from volumetric rate visualization -#define ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC (1 && ENABLE_2_5_0_ALPHA1) - - -//==================== -// 2.5.0.alpha1 techs -//==================== -#define ENABLE_2_5_0_ALPHA1 1 - // Enable editing volumes transformation in world coordinates and instances in local coordinates #define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_5_0_ALPHA1) // Enable showing world coordinates of volumes' offset relative to the instance containing them diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 1d8548bda9..ede915511e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -2,6 +2,9 @@ #include "GLGizmoMove.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GUI_App.hpp" +#if ENABLE_WORLD_COORDINATE +#include "slic3r/GUI/GUI_ObjectManipulation.hpp" +#endif // ENABLE_WORLD_COORDINATE #include @@ -18,18 +21,29 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam std::string GLGizmoMove3D::get_tooltip() const { +#if ENABLE_WORLD_COORDINATE + if (m_hover_id == 0) + return "X: " + format(m_displacement.x(), 2); + else if (m_hover_id == 1) + return "Y: " + format(m_displacement.y(), 2); + else if (m_hover_id == 2) + return "Z: " + format(m_displacement.z(), 2); + else + return ""; +#else const Selection& selection = m_parent.get_selection(); - bool show_position = selection.is_single_full_instance(); + const bool show_position = selection.is_single_full_instance(); const Vec3d& position = selection.get_bounding_box().center(); if (m_hover_id == 0 || m_grabbers[0].dragging) - return "X: " + format(show_position ? position(0) : m_displacement(0), 2); + return "X: " + format(show_position ? position.x() : m_displacement.x(), 2); else if (m_hover_id == 1 || m_grabbers[1].dragging) - return "Y: " + format(show_position ? position(1) : m_displacement(1), 2); + return "Y: " + format(show_position ? position.y() : m_displacement.y(), 2); else if (m_hover_id == 2 || m_grabbers[2].dragging) - return "Z: " + format(show_position ? position(2) : m_displacement(2), 2); + return "Z: " + format(show_position ? position.z() : m_displacement.z(), 2); else return ""; +#endif // ENABLE_WORLD_COORDINATE } bool GLGizmoMove3D::on_init() @@ -57,11 +71,35 @@ void GLGizmoMove3D::on_start_dragging() { if (m_hover_id != -1) { m_displacement = Vec3d::Zero(); +#if ENABLE_WORLD_COORDINATE + const Selection& selection = m_parent.get_selection(); +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); + if (coordinates_type == ECoordinatesType::World) +#else + if (wxGetApp().obj_manipul()->get_world_coordinates()) +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + m_starting_drag_position = m_center + m_grabbers[m_hover_id].center; +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_starting_drag_position = m_center + Geometry::assemble_transform(Vec3d::Zero(), v.get_instance_rotation()) * Geometry::assemble_transform(Vec3d::Zero(), v.get_volume_rotation()) * m_grabbers[m_hover_id].center; + } +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_starting_drag_position = m_center + Geometry::assemble_transform(Vec3d::Zero(), v.get_instance_rotation()) * m_grabbers[m_hover_id].center; + } + m_starting_box_center = m_center; + m_starting_box_bottom_center = m_center; + m_starting_box_bottom_center.z() = m_bounding_box.min.z(); +#else const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); m_starting_drag_position = m_grabbers[m_hover_id].center; m_starting_box_center = box.center(); m_starting_box_bottom_center = box.center(); - m_starting_box_bottom_center(2) = box.min(2); + m_starting_box_bottom_center.z() = box.min.z(); +#endif // ENABLE_WORLD_COORDINATE } } @@ -85,11 +123,30 @@ void GLGizmoMove3D::on_render() if (!m_cone.is_initialized()) m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0)); - const Selection& selection = m_parent.get_selection(); - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); +#if ENABLE_WORLD_COORDINATE + glsafe(::glPushMatrix()); + calc_selection_box_and_center(); + transform_to_local(m_parent.get_selection()); + + const Vec3d zero = Vec3d::Zero(); + const Vec3d half_box_size = 0.5 * m_bounding_box.size(); + + // x axis + m_grabbers[0].center = { half_box_size.x() + Offset, 0.0, 0.0 }; + m_grabbers[0].color = AXES_COLOR[0]; + + // y axis + m_grabbers[1].center = { 0.0, half_box_size.y() + Offset, 0.0 }; + m_grabbers[1].color = AXES_COLOR[1]; + + // z axis + m_grabbers[2].center = { 0.0, 0.0, half_box_size.z() + Offset }; + m_grabbers[2].color = AXES_COLOR[2]; +#else + const Selection& selection = m_parent.get_selection(); const BoundingBoxf3& box = selection.get_bounding_box(); const Vec3d& center = box.center(); @@ -104,24 +161,38 @@ void GLGizmoMove3D::on_render() // z axis m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset }; m_grabbers[2].color = AXES_COLOR[2]; +#endif // ENABLE_WORLD_COORDINATE glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); #if ENABLE_GLBEGIN_GLEND_REMOVAL +#if ENABLE_WORLD_COORDINATE + auto render_grabber_connection = [this, &zero](unsigned int id) { +#else auto render_grabber_connection = [this, ¢er](unsigned int id) { +#endif // ENABLE_WORLD_COORDINATE if (m_grabbers[id].enabled) { +#if ENABLE_WORLD_COORDINATE + if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(m_grabbers[id].center)) { + m_grabber_connections[id].old_center = m_grabbers[id].center; +#else if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) { m_grabber_connections[id].old_center = center; +#endif // ENABLE_WORLD_COORDINATE m_grabber_connections[id].model.reset(); GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; init_data.color = AXES_COLOR[id]; - init_data.reserve_vertices(2); - init_data.reserve_indices(2); + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices +#if ENABLE_WORLD_COORDINATE + init_data.add_vertex((Vec3f)zero.cast()); +#else init_data.add_vertex((Vec3f)center.cast()); +#endif // ENABLE_WORLD_COORDINATE init_data.add_vertex((Vec3f)m_grabbers[id].center.cast()); // indices @@ -150,7 +221,11 @@ void GLGizmoMove3D::on_render() if (m_grabbers[i].enabled) { glsafe(::glColor4fv(AXES_COLOR[i].data())); ::glBegin(GL_LINES); +#if ENABLE_WORLD_COORDINATE + ::glVertex3dv(zero.data()); +#else ::glVertex3dv(center.data()); +#endif // ENABLE_WORLD_COORDINATE ::glVertex3dv(m_grabbers[i].center.data()); glsafe(::glEnd()); } @@ -163,11 +238,19 @@ void GLGizmoMove3D::on_render() #endif // ENABLE_GLBEGIN_GLEND_REMOVAL // draw grabbers +#if ENABLE_WORLD_COORDINATE + render_grabbers(m_bounding_box); + for (unsigned int i = 0; i < 3; ++i) { + if (m_grabbers[i].enabled) + render_grabber_extension((Axis)i, m_bounding_box, false); + } +#else render_grabbers(box); for (unsigned int i = 0; i < 3; ++i) { if (m_grabbers[i].enabled) render_grabber_extension((Axis)i, box, false); } +#endif // ENABLE_WORLD_COORDINATE } else { // draw axis @@ -183,7 +266,11 @@ void GLGizmoMove3D::on_render() #else glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data())); ::glBegin(GL_LINES); +#if ENABLE_WORLD_COORDINATE + ::glVertex3dv(zero.data()); +#else ::glVertex3dv(center.data()); +#endif // ENABLE_WORLD_COORDINATE ::glVertex3dv(m_grabbers[m_hover_id].center.data()); glsafe(::glEnd()); @@ -193,40 +280,63 @@ void GLGizmoMove3D::on_render() shader->start_using(); shader->set_uniform("emission_factor", 0.1f); // draw grabber - float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); +#if ENABLE_WORLD_COORDINATE + const Vec3d box_size = m_bounding_box.size(); +#else + const Vec3d box_size = box.size(); +#endif // ENABLE_WORLD_COORDINATE + const float mean_size = (float)((box_size.x() + box_size.y() + box_size.z()) / 3.0); m_grabbers[m_hover_id].render(true, mean_size); shader->stop_using(); } +#if ENABLE_WORLD_COORDINATE + render_grabber_extension((Axis)m_hover_id, m_bounding_box, false); +#else render_grabber_extension((Axis)m_hover_id, box, false); +#endif // ENABLE_WORLD_COORDINATE } + +#if ENABLE_WORLD_COORDINATE + glsafe(::glPopMatrix()); +#endif // ENABLE_WORLD_COORDINATE } void GLGizmoMove3D::on_render_for_picking() { glsafe(::glDisable(GL_DEPTH_TEST)); +#if ENABLE_WORLD_COORDINATE + glsafe(::glPushMatrix()); + transform_to_local(m_parent.get_selection()); + render_grabbers_for_picking(m_bounding_box); + render_grabber_extension(X, m_bounding_box, true); + render_grabber_extension(Y, m_bounding_box, true); + render_grabber_extension(Z, m_bounding_box, true); + glsafe(::glPopMatrix()); +#else const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); render_grabbers_for_picking(box); render_grabber_extension(X, box, true); render_grabber_extension(Y, box, true); render_grabber_extension(Z, box, true); +#endif // ENABLE_WORLD_COORDINATE } double GLGizmoMove3D::calc_projection(const UpdateData& data) const { double projection = 0.0; - Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; - double len_starting_vec = starting_vec.norm(); + const Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; + const double len_starting_vec = starting_vec.norm(); if (len_starting_vec != 0.0) { - Vec3d mouse_dir = data.mouse_ray.unit_vector(); + const Vec3d mouse_dir = data.mouse_ray.unit_vector(); // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form // in our case plane normal and ray direction are the same (orthogonal view) // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal - Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + const Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; // vector from the starting position to the found intersection - Vec3d inters_vec = inters - m_starting_drag_position; + const Vec3d inters_vec = inters - m_starting_drag_position; // finds projection of the vector along the staring direction projection = inters_vec.dot(starting_vec.normalized()); @@ -240,8 +350,9 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) { - float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); - double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size)); + const Vec3d box_size = box.size(); + const float mean_size = float((box_size.x() + box_size.y() + box_size.z()) / 3.0); + const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size)); #if ENABLE_GLBEGIN_GLEND_REMOVAL GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); @@ -281,5 +392,58 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box shader->stop_using(); } +#if ENABLE_WORLD_COORDINATE +void GLGizmoMove3D::transform_to_local(const Selection& selection) const +{ + glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z())); + +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (!wxGetApp().obj_manipul()->is_world_coordinates()) { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + Transform3d orient_matrix = v.get_instance_transformation().get_matrix(true, false, true, true); + if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates()) + orient_matrix = orient_matrix * v.get_volume_transformation().get_matrix(true, false, true, true); + glsafe(::glMultMatrixd(orient_matrix.data())); + } +#else + if (!wxGetApp().obj_manipul()->get_world_coordinates()) { + const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); + glsafe(::glMultMatrixd(orient_matrix.data())); + } +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES +} + +void GLGizmoMove3D::calc_selection_box_and_center() +{ + const Selection& selection = m_parent.get_selection(); +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); + if (coordinates_type == ECoordinatesType::World) { +#else + if (wxGetApp().obj_manipul()->get_world_coordinates()) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + m_bounding_box = selection.get_bounding_box(); + m_center = m_bounding_box.center(); + } +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_bounding_box = v.transformed_convex_hull_bounding_box(v.get_instance_transformation().get_matrix(true, true, false, true) * v.get_volume_transformation().get_matrix(true, true, false, true)); + m_center = v.world_matrix() * m_bounding_box.center(); + } +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else { + m_bounding_box.reset(); + const Selection::IndicesList& ids = selection.get_volume_idxs(); + for (unsigned int id : ids) { + const GLVolume& v = *selection.get_volume(id); + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); + } + m_bounding_box = m_bounding_box.transformed(selection.get_volume(*ids.begin())->get_instance_transformation().get_matrix(true, true, false, true)); + m_center = selection.get_volume(*ids.begin())->get_instance_transformation().get_matrix(false, false, true, false) * m_bounding_box.center(); + } +} +#endif // ENABLE_WORLD_COORDINATE + } // namespace GUI } // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index 2a75df8669..10648d5b26 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -12,6 +12,10 @@ class GLGizmoMove3D : public GLGizmoBase static const double Offset; Vec3d m_displacement{ Vec3d::Zero() }; +#if ENABLE_WORLD_COORDINATE + Vec3d m_center{ Vec3d::Zero() }; + BoundingBoxf3 m_bounding_box; +#endif // ENABLE_WORLD_COORDINATE double m_snap_step{ 1.0 }; Vec3d m_starting_drag_position{ Vec3d::Zero() }; Vec3d m_starting_box_center{ Vec3d::Zero() }; @@ -50,6 +54,10 @@ protected: private: double calc_projection(const UpdateData& data) const; +#if ENABLE_WORLD_COORDINATE + void transform_to_local(const Selection& selection) const; + void calc_selection_box_and_center(); +#endif // ENABLE_WORLD_COORDINATE void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking); }; @@ -58,4 +66,4 @@ private: } // namespace GUI } // namespace Slic3r -#endif // slic3r_GLGizmoMove_hpp_ +#endif // slic3r_GLGizmoMove_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 565e9f2af2..5cf411271f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -2,15 +2,18 @@ #include "GLGizmoRotate.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/ImGuiWrapper.hpp" - -#include +#if ENABLE_WORLD_COORDINATE +#include "slic3r/GUI/GUI_ObjectManipulation.hpp" +#endif // ENABLE_WORLD_COORDINATE #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp" + #include "libslic3r/PresetBundle.hpp" -#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp" +#include namespace Slic3r { namespace GUI { @@ -58,6 +61,9 @@ bool GLGizmoRotate::on_init() void GLGizmoRotate::on_start_dragging() { +#if ENABLE_WORLD_COORDINATE + init_data_from_selection(m_parent.get_selection()); +#else const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); m_center = box.center(); m_radius = Offset + box.radius(); @@ -65,6 +71,7 @@ void GLGizmoRotate::on_start_dragging() m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; m_snap_fine_in_radius = m_radius; m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; +#endif // ENABLE_WORLD_COORDINATE } void GLGizmoRotate::on_update(const UpdateData& data) @@ -108,15 +115,21 @@ void GLGizmoRotate::on_render() m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0)); const Selection& selection = m_parent.get_selection(); +#if !ENABLE_WORLD_COORDINATE const BoundingBoxf3& box = selection.get_bounding_box(); +#endif // !ENABLE_WORLD_COORDINATE - if (m_hover_id != 0 && !m_grabbers.front().dragging) { + if (m_hover_id != 0 && !m_grabbers[0].dragging) { +#if ENABLE_WORLD_COORDINATE + init_data_from_selection(selection); +#else m_center = box.center(); m_radius = Offset + box.radius(); m_snap_coarse_in_radius = m_radius / 3.0f; m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; m_snap_fine_in_radius = m_radius; m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth); +#endif // ENABLE_WORLD_COORDINATE } const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset); @@ -170,8 +183,13 @@ void GLGizmoRotate::on_render() render_angle(); #endif // ENABLE_GLBEGIN_GLEND_REMOVAL +#if ENABLE_WORLD_COORDINATE + render_grabber(m_bounding_box); + render_grabber_extension(m_bounding_box, false); +#else render_grabber(box); render_grabber_extension(box, false); +#endif // ENABLE_WORLD_COORDINATE glsafe(::glPopMatrix()); } @@ -186,13 +204,74 @@ void GLGizmoRotate::on_render_for_picking() transform_to_local(selection); +#if ENABLE_WORLD_COORDINATE + render_grabbers_for_picking(m_bounding_box); + render_grabber_extension(m_bounding_box, true); +#else const BoundingBoxf3& box = selection.get_bounding_box(); render_grabbers_for_picking(box); render_grabber_extension(box, true); +#endif // ENABLE_WORLD_COORDINATE glsafe(::glPopMatrix()); } +#if ENABLE_WORLD_COORDINATE +void GLGizmoRotate::init_data_from_selection(const Selection& selection) +{ +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); + if (coordinates_type == ECoordinatesType::World) { +#else + if (wxGetApp().obj_manipul()->get_world_coordinates()) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + m_bounding_box = selection.get_bounding_box(); + m_center = m_bounding_box.center(); + } +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_bounding_box = v.transformed_convex_hull_bounding_box(v.get_instance_transformation().get_matrix(true, true, false, true) * v.get_volume_transformation().get_matrix(true, true, false, true)); + m_center = v.world_matrix() * m_bounding_box.center(); + } +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else { + m_bounding_box.reset(); + const Selection::IndicesList& ids = selection.get_volume_idxs(); + for (unsigned int id : ids) { + const GLVolume& v = *selection.get_volume(id); + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); + } + m_bounding_box = m_bounding_box.transformed(selection.get_volume(*ids.begin())->get_instance_transformation().get_matrix(true, true, false, true)); + m_center = selection.get_volume(*ids.begin())->get_instance_transformation().get_matrix(false, false, true, false) * m_bounding_box.center(); + } + + m_radius = Offset + m_bounding_box.radius(); + m_snap_coarse_in_radius = m_radius / 3.0f; + m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; + m_snap_fine_in_radius = m_radius; + m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; + +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (coordinates_type == ECoordinatesType::World) + m_orient_matrix = Transform3d::Identity(); + else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_orient_matrix = v.get_instance_transformation().get_matrix(true, false, true, true) * v.get_volume_transformation().get_matrix(true, false, true, true); + } + else { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_orient_matrix = v.get_instance_transformation().get_matrix(true, false, true, true); + } +#else + if (wxGetApp().obj_manipul()->get_world_coordinates()) + m_orient_matrix = Transform3d::Identity(); + else + m_orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES +} +#endif // ENABLE_WORLD_COORDINATE + void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit) { if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA) @@ -235,8 +314,8 @@ void GLGizmoRotate::render_circle() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(ScaleStepsCount); - init_data.reserve_indices(ScaleStepsCount); + init_data.vertices.reserve(ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices + indices for (unsigned short i = 0; i < ScaleStepsCount; ++i) { @@ -253,10 +332,10 @@ void GLGizmoRotate::render_circle() const #else ::glBegin(GL_LINE_LOOP); for (unsigned int i = 0; i < ScaleStepsCount; ++i) { - float angle = (float)i * ScaleStepRad; - float x = ::cos(angle) * m_radius; - float y = ::sin(angle) * m_radius; - float z = 0.0f; + const float angle = float(i) * ScaleStepRad; + const float x = ::cos(angle) * m_radius; + const float y = ::sin(angle) * m_radius; + const float z = 0.0f; ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); } glsafe(::glEnd()); @@ -278,8 +357,8 @@ void GLGizmoRotate::render_scale() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(2 * ScaleStepsCount); - init_data.reserve_indices(2 * ScaleStepsCount); + init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices + indices for (unsigned short i = 0; i < ScaleStepsCount; ++i) { @@ -337,8 +416,8 @@ void GLGizmoRotate::render_snap_radii() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(2 * ScaleStepsCount); - init_data.reserve_indices(2 * ScaleStepsCount); + init_data.vertices.reserve(2 * ScaleStepsCount * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * ScaleStepsCount * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices + indices for (unsigned short i = 0; i < ScaleStepsCount; ++i) { @@ -388,8 +467,8 @@ void GLGizmoRotate::render_reference_radius(const ColorRGBA& color, bool radius_ GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(2); - init_data.reserve_indices(2); + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); @@ -429,8 +508,8 @@ void GLGizmoRotate::render_angle() const GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(1 + AngleResolution); - init_data.reserve_indices(1 + AngleResolution); + init_data.vertices.reserve((1 + AngleResolution) * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve((1 + AngleResolution) * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices + indices for (unsigned short i = 0; i <= AngleResolution; ++i) { @@ -447,10 +526,10 @@ void GLGizmoRotate::render_angle() const #else ::glBegin(GL_LINE_STRIP); for (unsigned int i = 0; i <= AngleResolution; ++i) { - float angle = (float)i * step_angle; - float x = ::cos(angle) * ex_radius; - float y = ::sin(angle) * ex_radius; - float z = 0.0f; + const float angle = float(i) * step_angle; + const float x = ::cos(angle) * ex_radius; + const float y = ::sin(angle) * ex_radius; + const float z = 0.0f; ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); } glsafe(::glEnd()); @@ -466,8 +545,8 @@ void GLGizmoRotate::render_grabber_connection(const ColorRGBA& color, bool radiu GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(2); - init_data.reserve_indices(2); + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); @@ -558,10 +637,14 @@ void GLGizmoRotate::transform_to_local(const Selection& selection) const { glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z())); +#if ENABLE_WORLD_COORDINATE + glsafe(::glMultMatrixd(m_orient_matrix.data())); +#else if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) { const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); glsafe(::glMultMatrixd(orient_matrix.data())); } +#endif // ENABLE_WORLD_COORDINATE switch (m_axis) { @@ -614,8 +697,12 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons } } +#if ENABLE_WORLD_COORDINATE + m = m * m_orient_matrix.inverse(); +#else if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse(); +#endif // ENABLE_WORLD_COORDINATE m.translate(-m_center); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 4926c495cc..7153b884ed 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -29,11 +29,15 @@ private: Axis m_axis; double m_angle{ 0.0 }; Vec3d m_center{ Vec3d::Zero() }; - float m_radius{ 0.0f }; - float m_snap_coarse_in_radius{ 0.0f }; - float m_snap_coarse_out_radius{ 0.0f }; - float m_snap_fine_in_radius{ 0.0f }; - float m_snap_fine_out_radius{ 0.0f }; + float m_radius{ 0.0 }; + float m_snap_coarse_in_radius{ 0.0 }; + float m_snap_coarse_out_radius{ 0.0 }; + float m_snap_fine_in_radius{ 0.0 }; + float m_snap_fine_out_radius{ 0.0 }; +#if ENABLE_WORLD_COORDINATE + BoundingBoxf3 m_bounding_box; + Transform3d m_orient_matrix{ Transform3d::Identity() }; +#endif // ENABLE_WORLD_COORDINATE GLModel m_cone; #if ENABLE_GLBEGIN_GLEND_REMOVAL @@ -185,4 +189,4 @@ private: } // namespace GUI } // namespace Slic3r -#endif // slic3r_GLGizmoRotate_hpp_ +#endif // slic3r_GLGizmoRotate_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 4f7e375df3..b5e34ab998 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -2,6 +2,9 @@ #include "GLGizmoScale.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GUI_App.hpp" +#if ENABLE_WORLD_COORDINATE +#include "slic3r/GUI/GUI_ObjectManipulation.hpp" +#endif // ENABLE_WORLD_COORDINATE #include @@ -11,10 +14,10 @@ namespace Slic3r { namespace GUI { -const float GLGizmoScale3D::Offset = 5.0f; +const double GLGizmoScale3D::Offset = 5.0; GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) -: GLGizmoBase(parent, icon_filename, sprite_id) + : GLGizmoBase(parent, icon_filename, sprite_id) { #if ENABLE_GLBEGIN_GLEND_REMOVAL m_grabber_connections[0].grabber_indices = { 0, 1 }; @@ -31,14 +34,15 @@ std::string GLGizmoScale3D::get_tooltip() const { const Selection& selection = m_parent.get_selection(); - bool single_instance = selection.is_single_full_instance(); - bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); - - Vec3f scale = 100.0f * Vec3f::Ones(); - if (single_instance) - scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor().cast(); - else if (single_volume) - scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_scaling_factor().cast(); + Vec3d scale = 100.0 * Vec3d::Ones(); + if (selection.is_single_full_instance()) + scale = 100.0 * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor(); +#if ENABLE_WORLD_COORDINATE + else if (selection.is_single_volume_or_modifier()) +#else + else if (selection.is_single_modifier() || selection.is_single_volume()) +#endif // ENABLE_WORLD_COORDINATE + scale = 100.0 * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_scaling_factor(); if (m_hover_id == 0 || m_hover_id == 1 || m_grabbers[0].dragging || m_grabbers[1].dragging) return "X: " + format(scale.x(), 4) + "%"; @@ -64,15 +68,17 @@ bool GLGizmoScale3D::on_init() m_grabbers.push_back(Grabber()); } +#if !ENABLE_WORLD_COORDINATE double half_pi = 0.5 * (double)PI; // x axis - m_grabbers[0].angles(1) = half_pi; - m_grabbers[1].angles(1) = half_pi; + m_grabbers[0].angles.y() = half_pi; + m_grabbers[1].angles.y() = half_pi; // y axis - m_grabbers[2].angles(0) = half_pi; - m_grabbers[3].angles(0) = half_pi; + m_grabbers[2].angles.x() = half_pi; + m_grabbers[3].angles.x() = half_pi; +#endif // !ENABLE_WORLD_COORDINATE m_shortcut_key = WXK_CONTROL_S; @@ -93,9 +99,15 @@ bool GLGizmoScale3D::on_is_activable() const void GLGizmoScale3D::on_start_dragging() { if (m_hover_id != -1) { - m_starting.drag_position = m_grabbers[m_hover_id].center; m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL); - m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : m_parent.get_selection().get_bounding_box(); +#if ENABLE_WORLD_COORDINATE + m_starting.drag_position = m_grabbers_transform * m_grabbers[m_hover_id].center; + m_starting.box = m_bounding_box; + m_starting.center = m_center; + m_starting.instance_center = m_instance_center; +#else + m_starting.drag_position = m_grabbers[m_hover_id].center; + m_starting.box = (m_starting.ctrl_down && m_hover_id < 6) ? m_bounding_box : m_parent.get_selection().get_bounding_box(); const Vec3d& center = m_starting.box.center(); m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max.x(), center.y(), center.z()); @@ -104,6 +116,7 @@ void GLGizmoScale3D::on_start_dragging() m_starting.pivots[3] = m_transform * Vec3d(center.x(), m_starting.box.min.y(), center.z()); m_starting.pivots[4] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.max.z()); m_starting.pivots[5] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.min.z()); +#endif // ENABLE_WORLD_COORDINATE } } @@ -123,78 +136,176 @@ void GLGizmoScale3D::on_render() { const Selection& selection = m_parent.get_selection(); - bool single_instance = selection.is_single_full_instance(); - bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); - m_box.reset(); + m_bounding_box.reset(); +#if ENABLE_WORLD_COORDINATE + m_grabbers_transform = Transform3d::Identity(); + m_center = Vec3d::Zero(); + m_instance_center = Vec3d::Zero(); +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) { +#else + bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates(); + if (selection.is_single_full_instance() && !world_coordinates) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES +#else m_transform = Transform3d::Identity(); // Transforms grabbers' offsets to world refefence system Transform3d offsets_transform = Transform3d::Identity(); m_offsets_transform = Transform3d::Identity(); Vec3d angles = Vec3d::Zero(); - if (single_instance) { + if (selection.is_single_full_instance()) { +#endif // ENABLE_WORLD_COORDINATE // calculate bounding box in instance local reference system const Selection::IndicesList& idxs = selection.get_volume_idxs(); for (unsigned int idx : idxs) { - const GLVolume* vol = selection.get_volume(idx); - m_box.merge(vol->bounding_box().transformed(vol->get_volume_transformation().get_matrix())); + const GLVolume& v = *selection.get_volume(idx); +#if ENABLE_WORLD_COORDINATE + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); +#else + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix())); +#endif // ENABLE_WORLD_COORDINATE } +#if ENABLE_WORLD_COORDINATE + m_bounding_box = m_bounding_box.transformed(selection.get_volume(*idxs.begin())->get_instance_transformation().get_matrix(true, true, false, true)); +#endif // ENABLE_WORLD_COORDINATE + // gets transform from first selected volume - const GLVolume* v = selection.get_volume(*idxs.begin()); - m_transform = v->get_instance_transformation().get_matrix(); + const GLVolume& v = *selection.get_volume(*idxs.begin()); +#if ENABLE_WORLD_COORDINATE + m_grabbers_transform = v.get_instance_transformation().get_matrix(false, false, true) * Geometry::assemble_transform(m_bounding_box.center()); + m_center = selection.get_volume(*idxs.begin())->get_instance_transformation().get_matrix(false, false, true, false) * m_bounding_box.center(); + m_instance_center = v.get_instance_offset(); +#else + m_transform = v.get_instance_transformation().get_matrix(); + // gets angles from first selected volume - angles = v->get_instance_rotation(); + angles = v.get_instance_rotation(); // consider rotation+mirror only components of the transform for offsets - offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror()); + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror()); m_offsets_transform = offsets_transform; +#endif // ENABLE_WORLD_COORDINATE } - else if (single_volume) { - const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin()); - m_box = v->bounding_box(); - m_transform = v->world_matrix(); +#if ENABLE_WORLD_COORDINATE +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_instance_coordinates()) { +#else + else if (selection.is_single_volume_or_modifier() && !world_coordinates) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES +#else + else if (selection.is_single_modifier() || selection.is_single_volume()) { +#endif // ENABLE_WORLD_COORDINATE + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); +#if ENABLE_WORLD_COORDINATE +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_instance_transformation().get_matrix(true, true, false, true) * v.get_volume_transformation().get_matrix(true, false, false, true))); + Geometry::Transformation trafo(v.get_instance_transformation().get_matrix(true, false, true, true)); +#else + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_instance_transformation().get_matrix(true, true, false, true) * v.get_volume_transformation().get_matrix(true, true, false, true))); + Geometry::Transformation trafo(v.get_instance_transformation().get_matrix(true, false, true) * v.get_volume_transformation().get_matrix(true, false, true)); +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + trafo.set_offset(v.world_matrix().translation()); + m_grabbers_transform = trafo.get_matrix(); + m_center = v.world_matrix() * m_bounding_box.center(); + m_instance_center = m_center; + } +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates()) { + const GLVolume& v = *selection.get_volume(*selection.get_volume_idxs().begin()); + m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_instance_transformation().get_matrix(true, true, false, true) * v.get_volume_transformation().get_matrix(true, true, false, true))); + Geometry::Transformation trafo(v.get_instance_transformation().get_matrix(true, false, true, true) * v.get_volume_transformation().get_matrix(true, false, true, true)); + trafo.set_offset(v.world_matrix().translation()); + m_grabbers_transform = trafo.get_matrix(); + m_center = v.world_matrix() * m_bounding_box.center(); + m_instance_center = m_center; + } +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + else { + m_bounding_box = selection.get_bounding_box(); + m_grabbers_transform = Geometry::assemble_transform(m_bounding_box.center()); + m_center = m_bounding_box.center(); + m_instance_center = selection.is_single_full_instance() ? selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_offset() : m_center; + } +#else + m_bounding_box = v.bounding_box(); + m_transform = v.world_matrix(); angles = Geometry::extract_euler_angles(m_transform); // consider rotation+mirror only components of the transform for offsets - offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror()); - m_offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), v->get_volume_rotation(), Vec3d::Ones(), v->get_volume_mirror()); + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v.get_instance_mirror()); + m_offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), v.get_volume_rotation(), Vec3d::Ones(), v.get_volume_mirror()); } else - m_box = selection.get_bounding_box(); + m_bounding_box = selection.get_bounding_box(); - const Vec3d& center = m_box.center(); - Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0); - Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0); - Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset); + Vec3d offset_x = offsets_transform * (Offset * Vec3d::UnitX()); + Vec3d offset_y = offsets_transform * (Offset * Vec3d::UnitY()); + Vec3d offset_z = offsets_transform * (Offset * Vec3d::UnitZ()); - bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL)); + bool ctrl_down = m_dragging && m_starting.ctrl_down || !m_dragging && wxGetKeyState(WXK_CONTROL); +#endif // ENABLE_WORLD_COORDINATE +#if ENABLE_WORLD_COORDINATE // x axis - m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), center.z()) - offset_x; + const Vec3d box_half_size = 0.5 * m_bounding_box.size(); + bool use_constrain = wxGetKeyState(WXK_CONTROL) && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()); + + m_grabbers[0].center = { -(box_half_size.x() + Offset), 0.0, 0.0 }; + m_grabbers[0].color = (use_constrain && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0]; + m_grabbers[1].center = { box_half_size.x() + Offset, 0.0, 0.0 }; + m_grabbers[1].color = (use_constrain && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0]; + + // y axis + m_grabbers[2].center = { 0.0, -(box_half_size.y() + Offset), 0.0 }; + m_grabbers[2].color = (use_constrain && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1]; + m_grabbers[3].center = { 0.0, box_half_size.y() + Offset, 0.0 }; + m_grabbers[3].color = (use_constrain && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1]; + + // z axis + m_grabbers[4].center = { 0.0, 0.0, -(box_half_size.z() + Offset) }; + m_grabbers[4].color = (use_constrain && m_hover_id == 5) ? CONSTRAINED_COLOR : AXES_COLOR[2]; + m_grabbers[5].center = { 0.0, 0.0, box_half_size.z() + Offset }; + m_grabbers[5].color = (use_constrain && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2]; + + // uniform + m_grabbers[6].center = { -(box_half_size.x() + Offset), -(box_half_size.y() + Offset), 0.0 }; + m_grabbers[6].color = (use_constrain && m_hover_id == 8) ? CONSTRAINED_COLOR : m_highlight_color; + m_grabbers[7].center = { box_half_size.x() + Offset, -(box_half_size.y() + Offset), 0.0 }; + m_grabbers[7].color = (use_constrain && m_hover_id == 9) ? CONSTRAINED_COLOR : m_highlight_color; + m_grabbers[8].center = { box_half_size.x() + Offset, box_half_size.y() + Offset, 0.0 }; + m_grabbers[8].color = (use_constrain && m_hover_id == 6) ? CONSTRAINED_COLOR : m_highlight_color; + m_grabbers[9].center = { -(box_half_size.x() + Offset), box_half_size.y() + Offset, 0.0 }; + m_grabbers[9].color = (use_constrain && m_hover_id == 7) ? CONSTRAINED_COLOR : m_highlight_color; +#else + // x axis + const Vec3d center = m_bounding_box.center(); + + m_grabbers[0].center = m_transform * Vec3d(m_bounding_box.min.x(), center.y(), center.z()) - offset_x; m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0]; - m_grabbers[1].center = m_transform * Vec3d(m_box.max.x(), center.y(), center.z()) + offset_x; + m_grabbers[1].center = m_transform * Vec3d(m_bounding_box.max.x(), center.y(), center.z()) + offset_x; m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0]; // y axis - m_grabbers[2].center = m_transform * Vec3d(center.x(), m_box.min.y(), center.z()) - offset_y; + m_grabbers[2].center = m_transform * Vec3d(center.x(), m_bounding_box.min.y(), center.z()) - offset_y; m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1]; - m_grabbers[3].center = m_transform * Vec3d(center.x(), m_box.max.y(), center.z()) + offset_y; + m_grabbers[3].center = m_transform * Vec3d(center.x(), m_bounding_box.max.y(), center.z()) + offset_y; m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1]; // z axis - m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_box.min.z()) - offset_z; + m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.min.z()) - offset_z; m_grabbers[4].color = (ctrl_down && m_hover_id == 5) ? CONSTRAINED_COLOR : AXES_COLOR[2]; - m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_box.max.z()) + offset_z; + m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_bounding_box.max.z()) + offset_z; m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2]; // uniform - m_grabbers[6].center = m_transform * Vec3d(m_box.min.x(), m_box.min.y(), center.z()) - offset_x - offset_y; - m_grabbers[7].center = m_transform * Vec3d(m_box.max.x(), m_box.min.y(), center.z()) + offset_x - offset_y; - m_grabbers[8].center = m_transform * Vec3d(m_box.max.x(), m_box.max.y(), center.z()) + offset_x + offset_y; - m_grabbers[9].center = m_transform * Vec3d(m_box.min.x(), m_box.max.y(), center.z()) - offset_x + offset_y; + m_grabbers[6].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.min.y(), center.z()) - offset_x - offset_y; + m_grabbers[7].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.min.y(), center.z()) + offset_x - offset_y; + m_grabbers[8].center = m_transform * Vec3d(m_bounding_box.max.x(), m_bounding_box.max.y(), center.z()) + offset_x + offset_y; + m_grabbers[9].center = m_transform * Vec3d(m_bounding_box.min.x(), m_bounding_box.max.y(), center.z()) - offset_x + offset_y; + for (int i = 6; i < 10; ++i) { m_grabbers[i].color = m_highlight_color; } @@ -203,12 +314,18 @@ void GLGizmoScale3D::on_render() for (int i = 0; i < 10; ++i) { m_grabbers[i].angles = angles; } +#endif // ENABLE_WORLD_COORDINATE glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); +#if ENABLE_WORLD_COORDINATE + glsafe(::glPushMatrix()); + transform_to_local(selection); + const float grabber_mean_size = (float)((m_bounding_box.size().x() + m_bounding_box.size().y() + m_bounding_box.size().z()) / 3.0); +#else const BoundingBoxf3& selection_box = selection.get_bounding_box(); - float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0); +#endif // ENABLE_WORLD_COORDINATE if (m_hover_id == -1) { #if ENABLE_GLBEGIN_GLEND_REMOVAL @@ -266,7 +383,7 @@ void GLGizmoScale3D::on_render() shader = wxGetApp().get_shader("gouraud_light"); #else // draw connection - glsafe(::glColor4fv(m_grabbers[0].color.data())); + glsafe(::glColor4fv(AXES_COLOR[0].data())); render_grabbers_connection(0, 1); // draw grabbers @@ -294,7 +411,7 @@ void GLGizmoScale3D::on_render() shader = wxGetApp().get_shader("gouraud_light"); #else // draw connection - glsafe(::glColor4fv(m_grabbers[2].color.data())); + glsafe(::glColor4fv(AXES_COLOR[1].data())); render_grabbers_connection(2, 3); // draw grabbers @@ -322,7 +439,7 @@ void GLGizmoScale3D::on_render() shader = wxGetApp().get_shader("gouraud_light"); #else // draw connection - glsafe(::glColor4fv(m_grabbers[4].color.data())); + glsafe(::glColor4fv(AXES_COLOR[2].data())); render_grabbers_connection(4, 5); // draw grabbers @@ -371,12 +488,23 @@ void GLGizmoScale3D::on_render() shader->stop_using(); } } + +#if ENABLE_WORLD_COORDINATE + glsafe(::glPopMatrix()); +#endif // ENABLE_WORLD_COORDINATE } void GLGizmoScale3D::on_render_for_picking() { glsafe(::glDisable(GL_DEPTH_TEST)); +#if ENABLE_WORLD_COORDINATE + glsafe(::glPushMatrix()); + transform_to_local(m_parent.get_selection()); + render_grabbers_for_picking(m_bounding_box); + glsafe(::glPopMatrix()); +#else render_grabbers_for_picking(m_parent.get_selection().get_bounding_box()); +#endif // ENABLE_WORLD_COORDINATE } #if ENABLE_GLBEGIN_GLEND_REMOVAL @@ -403,8 +531,8 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int GLModel::Geometry init_data; init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; - init_data.reserve_vertices(2); - init_data.reserve_indices(2); + init_data.vertices.reserve(2 * GLModel::Geometry::vertex_stride_floats(init_data.format)); + init_data.indices.reserve(2 * GLModel::Geometry::index_stride_bytes(init_data.format)); // vertices init_data.add_vertex((Vec3f)m_grabbers[id_1].center.cast()); @@ -434,14 +562,96 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data) { +#if ENABLE_WORLD_COORDINATE double ratio = calc_ratio(data); + if (ratio > 0.0) { + Vec3d curr_scale = m_scale; + Vec3d starting_scale = m_starting.scale; + const Selection& selection = m_parent.get_selection(); +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); + if (coordinates_type == ECoordinatesType::World) { +#else + const bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates(); + if (world_coordinates) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_full_instance()) { + const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()); + curr_scale = (m * curr_scale).cwiseAbs(); + starting_scale = (m * starting_scale).cwiseAbs(); + } + else if (selection.is_single_volume_or_modifier()) { + const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()); + const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation()); + const Transform3d m = mi * mv; + curr_scale = (m * curr_scale).cwiseAbs(); + starting_scale = (m * starting_scale).cwiseAbs(); + } + } + + curr_scale(axis) = starting_scale(axis) * ratio; + +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (coordinates_type == ECoordinatesType::World) { +#else + if (world_coordinates) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_full_instance()) + m_scale = (Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse() * curr_scale).cwiseAbs(); + else if (selection.is_single_volume_or_modifier()) { + const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse(); + const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation()).inverse(); + m_scale = (mv * mi * curr_scale).cwiseAbs(); + } + else + m_scale = curr_scale; + } + else + m_scale = curr_scale; +#else + const double ratio = calc_ratio(data); if (ratio > 0.0) { m_scale(axis) = m_starting.scale(axis) * ratio; +#endif // ENABLE_WORLD_COORDINATE if (m_starting.ctrl_down) { +#if ENABLE_WORLD_COORDINATE + double local_offset = 0.5 * (ratio - 1.0) * m_starting.box.size()(axis); +#else double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis); +#endif // ENABLE_WORLD_COORDINATE + if (m_hover_id == 2 * axis) local_offset *= -1.0; +#if ENABLE_WORLD_COORDINATE + Vec3d center_offset = m_starting.instance_center - m_starting.center; +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_full_instance() && coordinates_type != ECoordinatesType::World) { +#else + if (selection.is_single_full_instance() && !world_coordinates) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse(); + center_offset = m * center_offset; + } + + local_offset += (ratio - 1.0) * center_offset(axis); + + switch (axis) + { + case X: { m_offset = local_offset * Vec3d::UnitX(); break; } + case Y: { m_offset = local_offset * Vec3d::UnitY(); break; } + case Z: { m_offset = local_offset * Vec3d::UnitZ(); break; } + default: { m_offset = Vec3d::Zero(); break; } + } + +#if !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_volume_or_modifier() && !world_coordinates) { + const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation()); + const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor()).inverse(); + m_offset = mv * mi * m_offset; + } +#endif // !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES +#else Vec3d local_offset_vec; switch (axis) { @@ -452,6 +662,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data) } m_offset = m_offsets_transform * local_offset_vec; +#endif // ENABLE_WORLD_COORDINATE } else m_offset = Vec3d::Zero(); @@ -460,9 +671,45 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data) void GLGizmoScale3D::do_scale_uniform(const UpdateData& data) { - double ratio = calc_ratio(data); + const double ratio = calc_ratio(data); if (ratio > 0.0) { m_scale = m_starting.scale * ratio; +#if ENABLE_WORLD_COORDINATE + if (m_starting.ctrl_down) { + m_offset = 0.5 * (ratio - 1.0) * m_starting.box.size(); + + if (m_hover_id == 6 || m_hover_id == 9) + m_offset.x() *= -1.0; + if (m_hover_id == 6 || m_hover_id == 7) + m_offset.y() *= -1.0; + + const Selection& selection = m_parent.get_selection(); +#if !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates(); +#endif // !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + Vec3d center_offset = m_starting.instance_center - m_starting.center; + +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) { +#else + if (selection.is_single_full_instance() && !world_coordinates) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse(); + center_offset = m * center_offset; + } + + m_offset += (ratio - 1.0) * center_offset; + +#if !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_volume_or_modifier() && !world_coordinates) { + const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation()); + const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor()).inverse(); + m_offset = mv * mi * m_offset; + } +#endif // !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + } + else +#endif // ENABLE_WORLD_COORDINATE m_offset = Vec3d::Zero(); } } @@ -471,22 +718,27 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const { double ratio = 0.0; - Vec3d pivot = (m_starting.ctrl_down && m_hover_id < 6) ? m_starting.pivots[m_hover_id] : m_starting.box.center(); +#if ENABLE_WORLD_COORDINATE + const Vec3d starting_vec = m_starting.drag_position - m_starting.center; +#else + const Vec3d pivot = (m_starting.ctrl_down && m_hover_id < 6) ? m_starting.pivots[m_hover_id] : m_starting.box.center(); + const Vec3d starting_vec = m_starting.drag_position - pivot; +#endif // ENABLE_WORLD_COORDINATE + + const double len_starting_vec = starting_vec.norm(); - Vec3d starting_vec = m_starting.drag_position - pivot; - double len_starting_vec = starting_vec.norm(); if (len_starting_vec != 0.0) { - Vec3d mouse_dir = data.mouse_ray.unit_vector(); + const Vec3d mouse_dir = data.mouse_ray.unit_vector(); // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form // in our case plane normal and ray direction are the same (orthogonal view) // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal - Vec3d inters = data.mouse_ray.a + (m_starting.drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + const Vec3d inters = data.mouse_ray.a + (m_starting.drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; // vector from the starting position to the found intersection - Vec3d inters_vec = inters - m_starting.drag_position; + const Vec3d inters_vec = inters - m_starting.drag_position; // finds projection of the vector along the staring direction - double proj = inters_vec.dot(starting_vec.normalized()); + const double proj = inters_vec.dot(starting_vec.normalized()); ratio = (len_starting_vec + proj) / len_starting_vec; } @@ -497,5 +749,27 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const return ratio; } +#if ENABLE_WORLD_COORDINATE +void GLGizmoScale3D::transform_to_local(const Selection& selection) const +{ + glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z())); + +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (!wxGetApp().obj_manipul()->is_world_coordinates()) { +#else + if (!wxGetApp().obj_manipul()->get_world_coordinates()) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates()) +#else + if (selection.is_single_volume_or_modifier()) +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + orient_matrix = orient_matrix * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_transformation().get_matrix(true, false, true, true); + glsafe(::glMultMatrixd(orient_matrix.data())); + } +} +#endif // ENABLE_WORLD_COORDINATE + } // namespace GUI } // namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp index 1584ccbfc0..01184a24e5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -5,29 +5,38 @@ #include "libslic3r/BoundingBox.hpp" - namespace Slic3r { namespace GUI { class GLGizmoScale3D : public GLGizmoBase { - static const float Offset; + static const double Offset; struct StartingData { - Vec3d scale; - Vec3d drag_position; + bool ctrl_down{ false }; + Vec3d scale{ Vec3d::Ones() }; + Vec3d drag_position{ Vec3d::Zero() }; +#if ENABLE_WORLD_COORDINATE + Vec3d center{ Vec3d::Zero() }; + Vec3d instance_center{ Vec3d::Zero() }; +#endif // ENABLE_WORLD_COORDINATE BoundingBoxf3 box; - Vec3d pivots[6]; - bool ctrl_down; - - StartingData() : scale(Vec3d::Ones()), drag_position(Vec3d::Zero()), ctrl_down(false) { for (int i = 0; i < 5; ++i) { pivots[i] = Vec3d::Zero(); } } +#if !ENABLE_WORLD_COORDINATE + std::array pivots{ Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero(), Vec3d::Zero() }; +#endif // !ENABLE_WORLD_COORDINATE }; - mutable BoundingBoxf3 m_box; - mutable Transform3d m_transform; + BoundingBoxf3 m_bounding_box; +#if ENABLE_WORLD_COORDINATE + Transform3d m_grabbers_transform; + Vec3d m_center{ Vec3d::Zero() }; + Vec3d m_instance_center{ Vec3d::Zero() }; +#else + Transform3d m_transform; // Transforms grabbers offsets to the proper reference system (world for instances, instance for volumes) - mutable Transform3d m_offsets_transform; + Transform3d m_offsets_transform; +#endif // ENABLE_WORLD_COORDINATE Vec3d m_scale{ Vec3d::Ones() }; Vec3d m_offset{ Vec3d::Zero() }; double m_snap_step{ 0.05 }; @@ -77,6 +86,9 @@ private: void do_scale_uniform(const UpdateData& data); double calc_ratio(const UpdateData& data) const; +#if ENABLE_WORLD_COORDINATE + void transform_to_local(const Selection& selection) const; +#endif // ENABLE_WORLD_COORDINATE }; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 9b362c4d49..381502d5b3 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -609,7 +609,7 @@ bool Selection::requires_uniform_scale() const if (!Geometry::is_rotation_ninety_degrees(Geometry::Transformation(get_volume(*m_list.begin())->world_matrix()).get_rotation())) { if (reason != nullptr) *reason = EUniformScaleRequiredReason::VolumeNotAxisAligned_World; - return true; + return true; } } else if (coord_type == ECoordinatesType::Instance) { @@ -624,7 +624,7 @@ bool Selection::requires_uniform_scale() const #else return !Geometry::is_rotation_ninety_degrees(Geometry::Transformation(get_volume(*m_list.begin())->world_matrix()).get_rotation()); #endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES - else if (is_single_full_instance()) + else if (is_single_full_instance()) { #if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES if (coord_type == ECoordinatesType::World) { if (!Geometry::is_rotation_ninety_degrees(get_volume(*m_list.begin())->get_instance_rotation())) { @@ -653,12 +653,14 @@ bool Selection::requires_uniform_scale() const } return false; } + } if (reason != nullptr) *reason = EUniformScaleRequiredReason::MultipleSelection; #else return wxGetApp().obj_manipul()->get_world_coordinates() ? !Geometry::is_rotation_ninety_degrees(get_volume(*m_list.begin())->get_instance_rotation()) : false; + } #endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES return true; @@ -939,7 +941,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ #else else if (is_single_volume() || is_single_modifier()) { if (transformation_type.independent()) - v.set_volume_rotation(m_cache.volumes_data[i] + rotation); + v.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation() + rotation); else { const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); const Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix()); @@ -1507,7 +1509,30 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) { #else if (is_single_full_instance() && !wxGetApp().obj_manipul()->get_world_coordinates()) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES glsafe(::glTranslated(center.x(), center.y(), center.z())); +#if ENABLE_WORLD_COORDINATE + Transform3d orient_matrix = Transform3d::Identity(); +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); +#else + if (boost::starts_with(sidebar_field, "position") || boost::starts_with(sidebar_field, "scale")) + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + else if (boost::starts_with(sidebar_field, "rotation")) { + if (boost::ends_with(sidebar_field, "x")) + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + else if (boost::ends_with(sidebar_field, "y")) { + const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation(); + if (rotation.x() == 0.0) + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + else + orient_matrix.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ())); + } + } +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + + glsafe(::glMultMatrixd(orient_matrix.data())); +#else if (!boost::starts_with(sidebar_field, "position")) { Transform3d orient_matrix = Transform3d::Identity(); if (boost::starts_with(sidebar_field, "scale")) @@ -1526,8 +1551,32 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) glsafe(::glMultMatrixd(orient_matrix.data())); } - } else if (is_single_volume() || is_single_modifier()) { +#endif // ENABLE_WORLD_COORDINATE + } +#if ENABLE_WORLD_COORDINATE + else if (is_single_volume_or_modifier()) { +#else + else if (is_single_volume() || is_single_modifier()) { +#endif // ENABLE_WORLD_COORDINATE glsafe(::glTranslated(center.x(), center.y(), center.z())); +#if ENABLE_WORLD_COORDINATE +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (!wxGetApp().obj_manipul()->is_world_coordinates()) { + Transform3d orient_matrix = Transform3d::Identity(); + if (wxGetApp().obj_manipul()->is_local_coordinates()) { +#else + if (!wxGetApp().obj_manipul()->get_world_coordinates()) { + Transform3d orient_matrix = Transform3d::Identity(); + if (boost::starts_with(sidebar_field, "scale")) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + const GLVolume* v = (*m_volumes)[*m_list.begin()]; + orient_matrix = v->get_instance_transformation().get_matrix(true, false, true, true) * v->get_volume_transformation().get_matrix(true, false, true, true); + } + else + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + glsafe(::glMultMatrixd(orient_matrix.data())); + } +#else Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); if (!boost::starts_with(sidebar_field, "position")) orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true);