From b76f9fc2eef4776d1945727f0c860e26f6d0102e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 19 May 2022 10:01:54 +0200 Subject: Tech ENABLE_TRANSFORMATIONS_BY_MATRICES - Scaling using object manipulator fields Fixed conflicts during rebase with master --- src/slic3r/GUI/GUI_ObjectList.cpp | 4 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 5 +- src/slic3r/GUI/Selection.cpp | 147 ++++++++++++++++++++++-------- src/slic3r/GUI/Selection.hpp | 46 +++++++++- 4 files changed, 159 insertions(+), 43 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 73946786d..a8c9819a6 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1585,8 +1585,8 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo if (from_galery) { #if ENABLE_TRANSFORMATIONS_BY_MATRICES - new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse()); // Transform the new modifier to be aligned with the print bed. + new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse()); const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box(); #else // Transform the new modifier to be aligned with the print bed. @@ -1662,8 +1662,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode // First (any) GLVolume of the selected instance. They all share the same instance matrix. const GLVolume* v = selection.get_first_volume(); #if ENABLE_TRANSFORMATIONS_BY_MATRICES - new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse()); // Transform the new modifier to be aligned with the print bed. + new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse()); const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box(); #else // Transform the new modifier to be aligned with the print bed. diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 74cb64e9f..ff8fe940c 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -1303,7 +1303,10 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const transformation_type.set_instance(); #if ENABLE_TRANSFORMATIONS_BY_MATRICES - Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale; + if (!selection.is_single_full_instance() && !selection.is_single_volume_or_modifier()) + transformation_type.set_relative(); + + const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale; #else if (!is_local_coordinates()) transformation_type.set_relative(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 4a60cbe63..be6abeee3 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -713,6 +713,8 @@ const BoundingBoxf3& Selection::get_bounding_box() const const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const { + assert(is_single_full_instance()); + if (!m_unscaled_instance_bounding_box.has_value()) { std::optional* bbox = const_cast*>(&m_unscaled_instance_bounding_box); *bbox = BoundingBoxf3(); @@ -736,6 +738,8 @@ const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const { + assert(is_single_full_instance()); + if (!m_scaled_instance_bounding_box.has_value()) { std::optional* bbox = const_cast*>(&m_scaled_instance_bounding_box); *bbox = BoundingBoxf3(); @@ -753,6 +757,65 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const return *m_scaled_instance_bounding_box; } +#if ENABLE_TRANSFORMATIONS_BY_MATRICES +const BoundingBoxf3& Selection::get_full_unscaled_instance_bounding_box() const +{ + assert(is_single_full_instance()); + + if (!m_full_unscaled_instance_bounding_box.has_value()) { + std::optional* bbox = const_cast*>(&m_full_unscaled_instance_bounding_box); + *bbox = BoundingBoxf3(); + if (m_valid) { + for (unsigned int i : m_list) { + const GLVolume& volume = *(*m_volumes)[i]; + Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix(); + trafo.translation().z() += volume.get_sla_shift_z(); + (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo)); + } + } + } + return *m_full_unscaled_instance_bounding_box; +} + +const BoundingBoxf3& Selection::get_full_scaled_instance_bounding_box() const +{ + assert(is_single_full_instance()); + + if (!m_full_scaled_instance_bounding_box.has_value()) { + std::optional* bbox = const_cast*>(&m_full_scaled_instance_bounding_box); + *bbox = BoundingBoxf3(); + if (m_valid) { + for (unsigned int i : m_list) { + const GLVolume& volume = *(*m_volumes)[i]; + Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix(); + trafo.translation().z() += volume.get_sla_shift_z(); + (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo)); + } + } + } + return *m_full_scaled_instance_bounding_box; +} + +const BoundingBoxf3& Selection::get_full_unscaled_instance_local_bounding_box() const +{ + assert(is_single_full_instance()); + + if (!m_full_unscaled_instance_local_bounding_box.has_value()) { + std::optional* bbox = const_cast*>(&m_full_unscaled_instance_local_bounding_box); + *bbox = BoundingBoxf3(); + if (m_valid) { + for (unsigned int i : m_list) { + const GLVolume& volume = *(*m_volumes)[i]; + Transform3d trafo = volume.get_volume_transformation().get_matrix(); + trafo.translation().z() += volume.get_sla_shift_z(); + (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo)); + } + } + } + return *m_full_unscaled_instance_local_bounding_box; +} +#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES + void Selection::setup_cache() { if (!m_valid) @@ -1350,54 +1413,66 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation if (!m_valid) return; + Vec3d relative_scale = scale; + for (unsigned int i : m_list) { 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) { - assert(is_from_fully_selected_instance(i)); - if (transformation_type.absolute()) { - assert(transformation_type.joint()); - v.set_instance_transformation(Geometry::assemble_transform(inst_trafo.get_offset_matrix(), inst_trafo.get_rotation_matrix(), - Geometry::scale_transform(scale), inst_trafo.get_mirror_matrix())); + + if (transformation_type.absolute()) { + // convert from absolute scaling to relative scaling + BoundingBoxf3 original_box; + if (m_mode == Instance) { + assert(is_from_fully_selected_instance(i)); + if (transformation_type.world()) + original_box = get_full_unscaled_instance_bounding_box(); + else + original_box = get_full_unscaled_instance_local_bounding_box(); } else { - if (transformation_type.world()) { - const Transform3d scale_matrix = Geometry::scale_transform(scale); - const Transform3d offset_matrix = (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) ? - // non-constrained scaling - add offset to scale around selection center - Geometry::translation_transform(m_cache.dragging_center + scale_matrix * (inst_trafo.get_offset() - m_cache.dragging_center)) : - // constrained scaling - add offset to keep constraint - Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix(); - v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset()); - } - else if (transformation_type.local()) { - const Transform3d scale_matrix = Geometry::scale_transform(scale); - Vec3d offset; - if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) { - // non-constrained scaling - add offset to scale around selection center - offset = inst_trafo.get_matrix_no_offset().inverse() * (inst_trafo.get_offset() - m_cache.dragging_center); - offset = inst_trafo.get_matrix_no_offset() * (scale_matrix * offset - offset); - } - else - // constrained scaling - add offset to keep constraint - offset = translation; - - v.set_instance_transformation(Geometry::translation_transform(offset) * inst_trafo.get_matrix() * scale_matrix); - } + if (transformation_type.world()) + original_box = v.transformed_convex_hull_bounding_box((volume_data.get_instance_transform() * + volume_data.get_volume_transform()).get_matrix_no_scaling_factor()); + else if (transformation_type.instance()) + original_box = v.transformed_convex_hull_bounding_box(volume_data.get_volume_transform().get_matrix_no_scaling_factor()); else - assert(false); + original_box = v.bounding_box(); } + + relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(m_box.get_bounding_box().size()); } - else { - if (transformation_type.absolute()) { - const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform(); - v.set_volume_transformation(Geometry::assemble_transform(volume_trafo.get_offset_matrix(), volume_trafo.get_rotation_matrix(), - Geometry::scale_transform(scale), volume_trafo.get_mirror_matrix())); + + if (m_mode == Instance) { + assert(is_from_fully_selected_instance(i)); + if (transformation_type.world()) { + const Transform3d scale_matrix = Geometry::scale_transform(relative_scale); + const Transform3d offset_matrix = (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) ? + // non-constrained scaling - add offset to scale around selection center + Geometry::translation_transform(m_cache.dragging_center + scale_matrix * (inst_trafo.get_offset() - m_cache.dragging_center)) : + // constrained scaling - add offset to keep constraint + Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix(); + v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset()); + } + else if (transformation_type.local()) { + const Transform3d scale_matrix = Geometry::scale_transform(relative_scale); + Vec3d offset; + if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) { + // non-constrained scaling - add offset to scale around selection center + offset = inst_trafo.get_matrix_no_offset().inverse() * (inst_trafo.get_offset() - m_cache.dragging_center); + offset = inst_trafo.get_matrix_no_offset() * (scale_matrix * offset - offset); + } + else + // constrained scaling - add offset to keep constraint + offset = translation; + + v.set_instance_transformation(Geometry::translation_transform(offset) * inst_trafo.get_matrix() * scale_matrix); } else - transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale)); + assert(false); } + else + transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale)); } #if !DISABLE_INSTANCES_SYNCH diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index c919927ea..a20e952f3 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -225,10 +225,24 @@ private: Cache m_cache; Clipboard m_clipboard; std::optional m_bounding_box; - // Bounding box of a selection, with no instance scaling applied. This bounding box - // is useful for absolute scaling of tilted objects in world coordinate space. + // Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied. + // This bounding box is useful for absolute scaling of tilted objects in world coordinate space. + // Modifiers are NOT taken in account std::optional m_unscaled_instance_bounding_box; + // Bounding box of a single full instance selection, in world coordinates. + // Modifiers are NOT taken in account std::optional m_scaled_instance_bounding_box; +#if ENABLE_TRANSFORMATIONS_BY_MATRICES + // Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied. + // Modifiers are taken in account + std::optional m_full_unscaled_instance_bounding_box; + // Bounding box of a single full instance selection, in world coordinates. + // Modifiers are taken in account + std::optional m_full_scaled_instance_bounding_box; + // Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied. + // Modifiers are taken in account + std::optional m_full_unscaled_instance_local_bounding_box; +#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_RENDER_SELECTION_CENTER GLModel m_vbo_sphere; @@ -355,10 +369,25 @@ public: unsigned int volumes_count() const { return (unsigned int)m_list.size(); } const BoundingBoxf3& get_bounding_box() const; - // Bounding box of a selection, with no instance scaling applied. This bounding box - // is useful for absolute scaling of tilted objects in world coordinate space. + // Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied. + // This bounding box is useful for absolute scaling of tilted objects in world coordinate space. + // Modifiers are NOT taken in account const BoundingBoxf3& get_unscaled_instance_bounding_box() const; + // Bounding box of a single full instance selection, in world coordinates. + // Modifiers are NOT taken in account const BoundingBoxf3& get_scaled_instance_bounding_box() const; +#if ENABLE_TRANSFORMATIONS_BY_MATRICES + // Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied. + // Modifiers are taken in account + const BoundingBoxf3& get_full_unscaled_instance_bounding_box() const; + // Bounding box of a single full instance selection, in world coordinates. + // Modifiers are taken in account + const BoundingBoxf3& get_full_scaled_instance_bounding_box() const; + + // Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied. + // Modifiers are taken in account + const BoundingBoxf3& get_full_unscaled_instance_local_bounding_box() const; +#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES void setup_cache(); @@ -429,7 +458,16 @@ private: void do_remove_volume(unsigned int volume_idx); void do_remove_instance(unsigned int object_idx, unsigned int instance_idx); void do_remove_object(unsigned int object_idx); +#if ENABLE_TRANSFORMATIONS_BY_MATRICES + void set_bounding_boxes_dirty() { + m_bounding_box.reset(); + m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); + m_full_unscaled_instance_bounding_box.reset(); m_full_scaled_instance_bounding_box.reset(); + m_full_unscaled_instance_local_bounding_box.reset();; + } +#else void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); } +#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES void render_synchronized_volumes(); #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_WORLD_COORDINATE -- cgit v1.2.3