From 7a263764e10ef838cdc69ccea6dbf281675777e3 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 4 Nov 2021 12:46:22 +0100 Subject: [PATCH] Tech ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES - Volumes rotation in all reference systems using Rotate gizmo and part manipulator fields --- src/slic3r/GUI/GUI_Geometry.hpp | 20 +++++++++++++------ src/slic3r/GUI/GUI_ObjectManipulation.cpp | 4 ++++ src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 24 ++++++++++++++++++----- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 9 ++++++++- src/slic3r/GUI/Selection.cpp | 16 +++++++++++++-- 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/GUI_Geometry.hpp b/src/slic3r/GUI/GUI_Geometry.hpp index 23dd36c39..029f01fb5 100644 --- a/src/slic3r/GUI/GUI_Geometry.hpp +++ b/src/slic3r/GUI/GUI_Geometry.hpp @@ -18,19 +18,25 @@ public: enum Enum { // Transforming in a world coordinate system World = 0, + // Transforming in a instance coordinate system + Instance = 1, // Transforming in a local coordinate system - Local = 1, + Local = 2, // Absolute transformations, allowed in local coordinate system only. Absolute = 0, // Relative transformations, allowed in both local and world coordinate system. - Relative = 2, + Relative = 4, // For group selection, the transformation is performed as if the group made a single solid body. Joint = 0, // For group selection, the transformation is performed on each object independently. - Independent = 4, + Independent = 8, World_Relative_Joint = World | Relative | Joint, World_Relative_Independent = World | Relative | Independent, + Instance_Absolute_Joint = Instance | Absolute | Joint, + Instance_Absolute_Independent = Instance | Absolute | Independent, + Instance_Relative_Joint = Instance | Relative | Joint, + Instance_Relative_Independent = Instance | Relative | Independent, Local_Absolute_Joint = Local | Absolute | Joint, Local_Absolute_Independent = Local | Absolute | Independent, Local_Relative_Joint = Local | Relative | Joint, @@ -44,14 +50,16 @@ public: Enum operator()() const { return m_value; } bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; } - void set_world() { this->remove(Local); } - void set_local() { this->add(Local); } + void set_world() { this->remove(Instance); this->remove(Local); } + void set_instance() { this->remove(Local); this->add(Instance); } + void set_local() { this->remove(Instance); this->add(Local); } void set_absolute() { this->remove(Relative); } void set_relative() { this->add(Relative); } void set_joint() { this->remove(Independent); } void set_independent() { this->add(Independent); } - bool world() const { return !this->has(Local); } + bool world() const { return !this->has(Instance) && !this->has(Local); } + bool instance() const { return this->has(Instance); } bool local() const { return this->has(Local); } bool absolute() const { return !this->has(Relative); } bool relative() const { return this->has(Relative); } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 0d2d55b28..acaa8d2b3 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -842,7 +842,11 @@ void ObjectManipulation::update_reset_buttons_visibility() bool show_drop_to_bed = false; #if ENABLE_WORLD_COORDINATE +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (m_coordinates_type != ECoordinatesType::Local && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier())) { +#else if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) { +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); Vec3d rotation = Vec3d::Zero(); Vec3d scale = Vec3d::Ones(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 4d82f5b9c..c6fb13e14 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -207,23 +207,32 @@ void GLGizmoRotate::on_render_for_picking() void GLGizmoRotate::init_data_from_selection(const Selection& selection) { #if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES - if (wxGetApp().obj_manipul()->is_world_coordinates()) { + 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())); + 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; @@ -231,13 +240,18 @@ void GLGizmoRotate::init_data_from_selection(const Selection& selection) m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; #if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES - if (wxGetApp().obj_manipul()->is_world_coordinates()) + 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 if (wxGetApp().obj_manipul()->get_world_coordinates()) -#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES 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 diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 7202f1bff..51d523d0f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -667,7 +667,14 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt) // Apply new temporary rotations #if ENABLE_WORLD_COORDINATE #if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES - TransformationType transformation_type = wxGetApp().obj_manipul()->is_world_coordinates() ? TransformationType::World_Relative_Joint : TransformationType::Local_Relative_Joint; + TransformationType transformation_type; + switch (wxGetApp().obj_manipul()->get_coordinates_type()) + { + default: + case ECoordinatesType::World: { transformation_type = TransformationType::World_Relative_Joint; break; } + case ECoordinatesType::Instance: { transformation_type = TransformationType::Instance_Relative_Joint; break; } + case ECoordinatesType::Local: { transformation_type = TransformationType::Local_Relative_Joint; break; } + } #else TransformationType transformation_type(wxGetApp().obj_manipul()->get_world_coordinates() ? TransformationType::World_Relative_Joint : TransformationType::Local_Relative_Joint); #endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index e388c8cbd..fc0a89d89 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -845,10 +845,11 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ const Vec3d new_rotation = transformation_type.world() ? Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix()) : transformation_type.absolute() ? rotation : Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix() * m); - if (rot_axis_max == 2 && transformation_type.joint()) { + const Vec3d relative_instance_offset = m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center; + if (rot_axis_max == 2 && transformation_type.joint() && !relative_instance_offset.isApprox(Vec3d::Zero())) { // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis. const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), new_rotation); - volume.set_instance_offset(m_cache.dragging_center + Eigen::AngleAxisd(z_diff, Vec3d::UnitZ()) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); + volume.set_instance_offset(m_cache.dragging_center + Eigen::AngleAxisd(z_diff, Vec3d::UnitZ()) * relative_instance_offset); } #else const Vec3d new_rotation = transformation_type.world() ? @@ -871,8 +872,19 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ rotate_instance(v, i); #if ENABLE_WORLD_COORDINATE else if (is_single_volume_or_modifier()) { +#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES + if (transformation_type.local()) { + const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); + v.set_volume_rotation(Geometry::extract_euler_angles(m_cache.volumes_data[i].get_volume_rotation_matrix() * m)); + } + else if (transformation_type.instance()) { + const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); + v.set_volume_rotation(Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix())); + } +#else if (transformation_type.local()) v.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation() + rotation); +#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES else { Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); m = m * m_cache.volumes_data[i].get_instance_rotation_matrix();