From ca6a5af1dc2412f7c8a5b0edff7cc18b8b7e37c4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 8 Apr 2019 13:35:03 +0200 Subject: [PATCH] Fixed rotation of SLA instances in case a rotation in X or Y was applied to the instances. --- src/libslic3r/Geometry.cpp | 24 ++++++++++++++++++++++++ src/libslic3r/Geometry.hpp | 7 +++++++ src/libslic3r/SLAPrint.cpp | 20 +++++++++++++------- src/slic3r/GUI/Selection.cpp | 30 +++--------------------------- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 8f3423a3d..a16b754a4 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1455,4 +1455,28 @@ Transformation Transformation::operator * (const Transformation& other) const return Transformation(get_matrix() * other.get_matrix()); } +Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) +{ + return + // From the current coordinate system to world. + Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) * + // From world to the initial coordinate system. + Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ()); +} + +// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis. +double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) +{ + Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); + Vec3d axis = angle_axis.axis(); + double angle = angle_axis.angle(); +#ifndef NDEBUG + if (std::abs(angle) > 1e-8) { + assert(std::abs(axis.x()) < 1e-8); + assert(std::abs(axis.y()) < 1e-8); + } +#endif /* NDEBUG */ + return (axis.z() < 0) ? -angle : angle; +} + } } diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index d556f664c..25b849d8c 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -262,6 +262,13 @@ public: Transformation operator * (const Transformation& other) const; }; +// Rotation when going from the first coordinate system with rotation rot_xyz_from applied +// to a coordinate system with rot_xyz_to applied. +extern Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to); +// Rotation by Z to align rot_xyz_from to rot_xyz_to. +// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis. +extern double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to); + } } #endif diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 694bc6444..5e590e7e2 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -3,6 +3,7 @@ #include "SLA/SLABasePool.hpp" #include "SLA/SLAAutoSupports.hpp" #include "ClipperUtils.hpp" +#include "Geometry.hpp" #include "MTUtils.hpp" #include @@ -103,13 +104,18 @@ static Transform3d sla_trafo(const ModelObject &model_object) static std::vector sla_instances(const ModelObject &model_object) { std::vector instances; - for (ModelInstance *model_instance : model_object.instances) - if (model_instance->is_printable()) { - instances.emplace_back( - model_instance->id(), - Point::new_scale(model_instance->get_offset(X), model_instance->get_offset(Y)), - float(model_instance->get_rotation(Z))); - } + assert(! model_object.instances.empty()); + if (! model_object.instances.empty()) { + Vec3d rotation0 = model_object.instances.front()->get_rotation(); + rotation0(2) = 0.; + for (ModelInstance *model_instance : model_object.instances) + if (model_instance->is_printable()) { + instances.emplace_back( + model_instance->id(), + Point::new_scale(model_instance->get_offset(X), model_instance->get_offset(Y)), + float(Geometry::rotation_diff_z(rotation0, model_instance->get_rotation()))); + } + } return instances; } diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 00ff2dd06..6f148ca24 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -482,30 +482,6 @@ void Selection::translate(const Vec3d& displacement, bool local) m_bounding_box_dirty = true; } -static Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) -{ - return - // From the current coordinate system to world. - Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) * - // From world to the initial coordinate system. - Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ()); -} - -// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis. -static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) -{ - Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); - Vec3d axis = angle_axis.axis(); - double angle = angle_axis.angle(); -#ifndef NDEBUG - if (std::abs(angle) > 1e-8) { - assert(std::abs(axis.x()) < 1e-8); - assert(std::abs(axis.y()) < 1e-8); - } -#endif /* NDEBUG */ - return (axis.z() < 0) ? -angle : angle; -} - // Rotate an object around one of the axes. Only one rotation component is expected to be changing. void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type) { @@ -548,7 +524,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ assert(is_approx(rotation.z(), 0.0)); const GLVolume &first_volume = *(*m_volumes)[first_volume_idx]; const Vec3d &rotation = first_volume.get_instance_rotation(); - double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation()); + double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation()); volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff)); } else { @@ -1538,7 +1514,7 @@ void Selection::render_sidebar_size_hint(Axis axis, double length) const #ifndef NDEBUG static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) { - Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); + Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); Vec3d axis = angle_axis.axis(); double angle = angle_axis.angle(); if (std::abs(angle) < 1e-8) @@ -1618,7 +1594,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ break; case SYNC_ROTATION_GENERAL: // generic rotation -> update instance z with the delta of the rotation. - double z_diff = rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()); + double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()); v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff)); break; }