diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index f7951f97ca..345d733afd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -238,13 +238,7 @@ void GLGizmoRotate::init_data_from_selection(const Selection& selection) selection.get_bounding_box_in_reference_system(ECoordinatesType::Local) : selection.get_bounding_box_in_current_reference_system(); m_bounding_box = box; m_center = box_trafo.translation(); - m_orient_matrix = Geometry::translation_transform(m_center); - if (!wxGetApp().obj_manipul()->is_world_coordinates() || m_force_local_coordinate) { - const GLVolume& v = *selection.get_first_volume(); - m_orient_matrix = m_orient_matrix * v.get_instance_transformation().get_rotation_matrix(); - if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates() || m_force_local_coordinate) - m_orient_matrix = m_orient_matrix * v.get_volume_transformation().get_rotation_matrix(); - } + m_orient_matrix = box_trafo; m_radius = Offset + m_bounding_box.radius(); m_snap_coarse_in_radius = m_radius / 3.0f; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index c6150ed68f..4e9ac43ea8 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -918,7 +918,7 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement); } else - transform_instance_relative_world(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center); + transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center); } else { if (transformation_type.local() && transformation_type.absolute()) { @@ -998,24 +998,24 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ assert(transformation_type.relative() || (transformation_type.absolute() && transformation_type.local())); - Transform3d rotation_matrix = Geometry::rotation_transform(rotation); - for (unsigned int i : m_list) { + Transform3d rotation_matrix = Geometry::rotation_transform(rotation); GLVolume& v = *(*m_volumes)[i]; const VolumeCache& volume_data = m_cache.volumes_data[i]; const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform(); if (m_mode == Instance && !is_wipe_tower()) { assert(is_from_fully_selected_instance(i)); if (transformation_type.instance()) { - const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset(); - const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot; - Matrix3d inst_rotation, inst_scale; - inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale); - const Transform3d trafo = inst_trafo.get_rotation_matrix() * rotation_matrix; - v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * inst_trafo.get_offset_matrix() * trafo * Transform3d(inst_scale) * Geometry::translation_transform(-local_inst_pivot)); + // ensure that the instance rotates as a rigid body + const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset(); + const Transform3d inst_rotation_matrix = inst_trafo.get_rotation_matrix(); + rotation_matrix = inst_matrix_no_offset.inverse() * inst_rotation_matrix * rotation_matrix * inst_rotation_matrix.inverse() * inst_matrix_no_offset; + + // rotate around selection center + const Vec3d inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * (m_cache.dragging_center - inst_trafo.get_offset()); + rotation_matrix = Geometry::translation_transform(inst_pivot) * rotation_matrix * Geometry::translation_transform(-inst_pivot); } - else - transform_instance_relative_world(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); + transform_instance_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); } else { if (!is_single_volume_or_modifier()) { @@ -1024,27 +1024,19 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ } else { if (transformation_type.instance()) { - // ensure proper sign of rotation for mirrored objects - if (inst_trafo.is_left_handed() && !rotation.normalized().isApprox(Vec3d::UnitX())) - rotation_matrix = rotation_matrix.inverse(); - // ensure that the volume rotates as a rigid body const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix; } else { if (transformation_type.local()) { - const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform(); - const Geometry::Transformation world_trafo = inst_trafo * vol_trafo; - // ensure proper sign of rotation for mirrored objects - if (world_trafo.is_left_handed() && !rotation.normalized().isApprox(Vec3d::UnitX())) - rotation_matrix = rotation_matrix.inverse(); - // ensure that the volume rotates as a rigid body - if (Geometry::TransformationSVD(world_trafo).anisotropic_scale) { - const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); - rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix; - } + const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform(); + const Transform3d vol_matrix_no_offset = vol_trafo.get_matrix_no_offset(); + const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); + const Transform3d vol_rotation_matrix = vol_trafo.get_rotation_matrix(); + rotation_matrix = vol_matrix_no_offset.inverse() * inst_scale_matrix.inverse() * vol_rotation_matrix * rotation_matrix * + vol_rotation_matrix.inverse() * inst_scale_matrix * vol_matrix_no_offset; } } transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); @@ -1458,7 +1450,7 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo * Geometry::translation_transform(-local_inst_pivot)); } else - transform_instance_relative_world(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center); + transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center); } else { if (!is_single_volume_or_modifier()) { @@ -3331,16 +3323,21 @@ void Selection::paste_objects_from_clipboard() } #if ENABLE_WORLD_COORDINATE -void Selection::transform_instance_relative_world(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, +void Selection::transform_instance_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, const Transform3d& transform, const Vec3d& world_pivot) { assert(transformation_type.relative()); - assert(transformation_type.world()); const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform(); - const Vec3d inst_pivot = transformation_type.independent() && !is_from_single_instance() ? inst_trafo.get_offset() : world_pivot; - const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot); - volume.set_instance_transformation(trafo * inst_trafo.get_matrix()); + if (transformation_type.world()) { + const Vec3d inst_pivot = transformation_type.independent() && !is_from_single_instance() ? inst_trafo.get_offset() : world_pivot; + const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot); + volume.set_instance_transformation(trafo * inst_trafo.get_matrix()); + } + else if (transformation_type.instance()) + volume.set_instance_transformation(inst_trafo.get_matrix() * transform); + else + assert(false); } void Selection::transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 4c818f30ce..eb69d44919 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -516,7 +516,7 @@ private: void paste_objects_from_clipboard(); #if ENABLE_WORLD_COORDINATE - void transform_instance_relative_world(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, + void transform_instance_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, const Transform3d& transform, const Vec3d& world_pivot); void transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, const Transform3d& transform, const Vec3d& world_pivot);