From bb18edde0ab384276d1ee94219cd76b6d8f4310c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 5 May 2021 11:53:24 +0200 Subject: [PATCH] Tech ENABLE_ALLOW_NEGATIVE_Z-> Synchronize sinking instances --- src/slic3r/GUI/Selection.cpp | 178 +++++++++++++++-------------------- src/slic3r/GUI/Selection.hpp | 2 +- 2 files changed, 79 insertions(+), 101 deletions(-) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 3ab546abe..8d7878650 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -58,13 +58,11 @@ bool Selection::Clipboard::is_sla_compliant() const if (m_mode == Selection::Volume) return false; - for (const ModelObject* o : m_model->objects) - { + for (const ModelObject* o : m_model->objects) { if (o->is_multiparts()) return false; - for (const ModelVolume* v : o->volumes) - { + for (const ModelVolume* v : o->volumes) { if (v->is_modifier()) return false; } @@ -78,7 +76,8 @@ Selection::Clipboard::Clipboard() m_model.reset(new Model); } -void Selection::Clipboard::reset() { +void Selection::Clipboard::reset() +{ m_model->clear_objects(); } @@ -149,7 +148,7 @@ void Selection::set_model(Model* model) void Selection::add(unsigned int volume_idx, bool as_single_selection, bool check_for_already_contained) { - if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx)) + if (!m_valid || (unsigned int)m_volumes->size() <= volume_idx) return; const GLVolume* volume = (*m_volumes)[volume_idx]; @@ -167,8 +166,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec needs_reset |= as_single_selection && !is_any_modifier() && volume->is_modifier; needs_reset |= is_any_modifier() && !volume->is_modifier; - if (!already_contained || needs_reset) - { + if (!already_contained || needs_reset) { wxGetApp().plater()->take_snapshot(_L("Selection-Add")); if (needs_reset) @@ -185,7 +183,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec { case Volume: { - if ((volume->volume_idx() >= 0) && (is_empty() || (volume->instance_idx() == get_instance_idx()))) + if (volume->volume_idx() >= 0 && (is_empty() || volume->instance_idx() == get_instance_idx())) do_add_volume(volume_idx); break; @@ -204,7 +202,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec void Selection::remove(unsigned int volume_idx) { - if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx)) + if (!m_valid || (unsigned int)m_volumes->size() <= volume_idx) return; if (!contains_volume(volume_idx)) @@ -333,10 +331,9 @@ void Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx) if (!m_valid) return; - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) - { + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { GLVolume* v = (*m_volumes)[i]; - if ((v->object_idx() == (int)object_idx) && (v->volume_idx() == (int)volume_idx)) + if (v->object_idx() == (int)object_idx && v->volume_idx() == (int)volume_idx) do_remove_volume(i); } @@ -358,8 +355,7 @@ void Selection::add_volumes(EMode mode, const std::vector& volume_ clear(); m_mode = mode; - for (unsigned int i : volume_idxs) - { + for (unsigned int i : volume_idxs) { if (i < (unsigned int)m_volumes->size()) do_add_volume(i); } @@ -374,8 +370,7 @@ void Selection::remove_volumes(EMode mode, const std::vector& volu return; m_mode = mode; - for (unsigned int i : volume_idxs) - { + for (unsigned int i : volume_idxs) { if (i < (unsigned int)m_volumes->size()) do_remove_volume(i); } @@ -390,8 +385,7 @@ void Selection::add_all() return; unsigned int count = 0; - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) - { + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { if (!(*m_volumes)[i]->is_wipe_tower) ++count; } @@ -404,8 +398,7 @@ void Selection::add_all() m_mode = Instance; clear(); - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) - { + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { if (!(*m_volumes)[i]->is_wipe_tower) do_add_volume(i); } @@ -455,8 +448,7 @@ void Selection::clear() if (m_list.empty()) return; - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { (*m_volumes)[i]->selected = false; } @@ -522,16 +514,15 @@ bool Selection::is_single_full_instance() const return false; int object_idx = m_valid ? get_object_idx() : -1; - if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx)) + if (object_idx < 0 || (int)m_model->objects.size() <= object_idx) return false; int instance_idx = (*m_volumes)[*m_list.begin()]->instance_idx(); std::set volumes_idxs; - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { const GLVolume* v = (*m_volumes)[i]; - if ((object_idx != v->object_idx()) || (instance_idx != v->instance_idx())) + if (object_idx != v->object_idx() || instance_idx != v->instance_idx()) return false; int volume_idx = v->volume_idx(); @@ -544,8 +535,8 @@ bool Selection::is_single_full_instance() const bool Selection::is_from_single_object() const { - int idx = get_object_idx(); - return (0 <= idx) && (idx < 1000); + const int idx = get_object_idx(); + return 0 <= idx && idx < 1000; } bool Selection::is_sla_compliant() const @@ -553,8 +544,7 @@ bool Selection::is_sla_compliant() const if (m_mode == Volume) return false; - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { if ((*m_volumes)[i]->is_modifier) return false; } @@ -564,8 +554,7 @@ bool Selection::is_sla_compliant() const bool Selection::contains_all_volumes(const std::vector& volume_idxs) const { - for (unsigned int i : volume_idxs) - { + for (unsigned int i : volume_idxs) { if (m_list.find(i) == m_list.end()) return false; } @@ -575,8 +564,7 @@ bool Selection::contains_all_volumes(const std::vector& volume_idx bool Selection::contains_any_volume(const std::vector& volume_idxs) const { - for (unsigned int i : volume_idxs) - { + for (unsigned int i : volume_idxs) { if (m_list.find(i) != m_list.end()) return true; } @@ -588,8 +576,7 @@ bool Selection::matches(const std::vector& volume_idxs) const { unsigned int count = 0; - for (unsigned int i : volume_idxs) - { + for (unsigned int i : volume_idxs) { if (m_list.find(i) != m_list.end()) ++count; else @@ -614,8 +601,7 @@ int Selection::get_object_idx() const int Selection::get_instance_idx() const { - if (m_cache.content.size() == 1) - { + if (m_cache.content.size() == 1) { const InstanceIdxsList& idxs = m_cache.content.begin()->second; if (idxs.size() == 1) return *idxs.begin(); @@ -673,12 +659,11 @@ void Selection::translate(const Vec3d& displacement, bool local) EMode translation_type = m_mode; for (unsigned int i : m_list) { - if (m_mode == Volume || (*m_volumes)[i]->is_wipe_tower) - { + if (m_mode == Volume || (*m_volumes)[i]->is_wipe_tower) { if (local) (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement); else { - Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; + const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); } } @@ -686,7 +671,7 @@ void Selection::translate(const Vec3d& displacement, bool local) if (is_from_fully_selected_instance(i)) (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); else { - Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; + const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); translation_type = Volume; } @@ -714,18 +699,14 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ if (!is_wipe_tower()) { int rot_axis_max = 0; - if (rotation.isApprox(Vec3d::Zero())) - { - for (unsigned int i : m_list) - { + if (rotation.isApprox(Vec3d::Zero())) { + for (unsigned int i : m_list) { GLVolume &volume = *(*m_volumes)[i]; - if (m_mode == Instance) - { + if (m_mode == Instance) { volume.set_instance_rotation(m_cache.volumes_data[i].get_instance_rotation()); volume.set_instance_offset(m_cache.volumes_data[i].get_instance_position()); } - else if (m_mode == Volume) - { + else if (m_mode == Volume) { volume.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation()); volume.set_volume_offset(m_cache.volumes_data[i].get_volume_position()); } @@ -742,14 +723,14 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it. std::vector object_instance_first(m_model->objects.size(), -1); auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) { - int first_volume_idx = object_instance_first[volume.object_idx()]; + const int first_volume_idx = object_instance_first[volume.object_idx()]; if (rot_axis_max != 2 && first_volume_idx != -1) { // Generic rotation, but no rotation around the Z axis. // Always do a local rotation (do not consider the selection to be a rigid body). 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 = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation()); + const 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 { @@ -759,7 +740,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation(); if (rot_axis_max == 2 && transformation_type.joint()) { // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis. - double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), new_rotation); + 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_rotation(new_rotation); @@ -767,19 +748,16 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ } }; - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { GLVolume &volume = *(*m_volumes)[i]; if (is_single_full_instance()) rotate_instance(volume, i); - else if (is_single_volume() || is_single_modifier()) - { + else if (is_single_volume() || is_single_modifier()) { if (transformation_type.independent()) volume.set_volume_rotation(volume.get_volume_rotation() + rotation); - else - { - Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); - Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix()); + 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()); volume.set_volume_rotation(new_rotation); } } @@ -787,15 +765,13 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ { if (m_mode == Instance) rotate_instance(volume, i); - else if (m_mode == Volume) - { + else if (m_mode == Volume) { // extracts rotations from the composed transformation Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix()); - if (transformation_type.joint()) - { - Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center; - Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot); + if (transformation_type.joint()) { + const Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center; + const Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot); volume.set_volume_offset(local_pivot + offset); } volume.set_volume_rotation(new_rotation); @@ -816,8 +792,8 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ // make sure the wipe tower rotates around its center, not origin // we can assume that only Z rotation changes - Vec3d center_local = volume.transformed_bounding_box().center() - volume.get_volume_offset(); - Vec3d center_local_new = Eigen::AngleAxisd(rotation(2)-volume.get_volume_rotation()(2), Vec3d(0, 0, 1)) * center_local; + const Vec3d center_local = volume.transformed_bounding_box().center() - volume.get_volume_offset(); + const Vec3d center_local_new = Eigen::AngleAxisd(rotation(2)-volume.get_volume_rotation()(2), Vec3d(0.0, 0.0, 1.0)) * center_local; volume.set_volume_rotation(rotation); volume.set_volume_offset(volume.get_volume_offset() + center_local - center_local_new); } @@ -835,8 +811,7 @@ void Selection::flattening_rotate(const Vec3d& normal) if (!m_valid) return; - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { // Normal transformed from the object coordinate space to the world coordinate space. const auto &voldata = m_cache.volumes_data[i]; Vec3d tnormal = (Geometry::assemble_transform( @@ -1781,18 +1756,16 @@ void Selection::render_synchronized_volumes() const float color[3] = { 1.0f, 1.0f, 0.0f }; - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { const GLVolume* volume = (*m_volumes)[i]; int object_idx = volume->object_idx(); int volume_idx = volume->volume_idx(); - for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) - { + for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) { if (i == j) continue; const GLVolume* v = (*m_volumes)[j]; - if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx)) + if (v->object_idx() != object_idx || v->volume_idx() != volume_idx) continue; render_bounding_box(v->transformed_convex_hull_bounding_box(), color); @@ -1986,7 +1959,7 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); ::glBegin(GL_QUADS); - if ((camera_on_top && (type == 1)) || (!camera_on_top && (type == 2))) + if ((camera_on_top && type == 1) || (!camera_on_top && type == 2)) ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); else ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); @@ -1997,7 +1970,7 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co glsafe(::glEnd()); ::glBegin(GL_QUADS); - if ((camera_on_top && (type == 2)) || (!camera_on_top && (type == 1))) + if ((camera_on_top && type == 2) || (!camera_on_top && type == 1)) ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); else ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); @@ -2014,9 +1987,9 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co #ifndef NDEBUG static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &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(); + const Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); + const Vec3d axis = angle_axis.axis(); + const double angle = angle_axis.angle(); if (std::abs(angle) < 1e-8) return true; assert(std::abs(axis.x()) < 1e-8); @@ -2053,24 +2026,22 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ std::set done; // prevent processing volumes twice done.insert(m_list.begin(), m_list.end()); - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { if (done.size() == m_volumes->size()) break; const GLVolume* volume = (*m_volumes)[i]; - int object_idx = volume->object_idx(); + const int object_idx = volume->object_idx(); if (object_idx >= 1000) continue; - int instance_idx = volume->instance_idx(); + const int instance_idx = volume->instance_idx(); const Vec3d& rotation = volume->get_instance_rotation(); const Vec3d& scaling_factor = volume->get_instance_scaling_factor(); const Vec3d& mirror = volume->get_instance_mirror(); // Process unselected instances. - for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) - { + for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) { if (done.size() == m_volumes->size()) break; @@ -2078,24 +2049,33 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ continue; GLVolume* v = (*m_volumes)[j]; - if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx)) + if (v->object_idx() != object_idx || v->instance_idx() == instance_idx) continue; assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation())); switch (sync_rotation_type) { - case SYNC_ROTATION_NONE: + case SYNC_ROTATION_NONE: { +#if ENABLE_ALLOW_NEGATIVE_Z + // z only rotation -> synch instance z + // The X,Y rotations should be synchronized from start to end of the rotation. + assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation())); + v->set_instance_offset(Z, volume->get_instance_offset().z()); + break; +#else // z only rotation -> keep instance z // The X,Y rotations should be synchronized from start to end of the rotation. assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation())); break; +#endif // ENABLE_ALLOW_NEGATIVE_Z + } case SYNC_ROTATION_FULL: // rotation comes from place on face -> force given z - v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2))); + v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() }); break; case SYNC_ROTATION_GENERAL: // generic rotation -> update instance z with the delta of the 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)); + const 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({ rotation.x(), rotation.y(), rotation.z() + z_diff }); break; } @@ -2113,27 +2093,25 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ void Selection::synchronize_unselected_volumes() { - for (unsigned int i : m_list) - { + for (unsigned int i : m_list) { const GLVolume* volume = (*m_volumes)[i]; - int object_idx = volume->object_idx(); + const int object_idx = volume->object_idx(); if (object_idx >= 1000) continue; - int volume_idx = volume->volume_idx(); + const int volume_idx = volume->volume_idx(); const Vec3d& offset = volume->get_volume_offset(); const Vec3d& rotation = volume->get_volume_rotation(); const Vec3d& scaling_factor = volume->get_volume_scaling_factor(); const Vec3d& mirror = volume->get_volume_mirror(); // Process unselected volumes. - for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) - { + for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) { if (j == i) continue; GLVolume* v = (*m_volumes)[j]; - if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx)) + if (v->object_idx() != object_idx || v->volume_idx() != volume_idx) continue; v->set_volume_offset(offset); diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 8bb418baa..c28a6e867 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -129,7 +129,7 @@ private: TransformCache m_instance; public: - VolumeCache() {} + VolumeCache() = default; VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform); const Vec3d& get_volume_position() const { return m_volume.position; }