From 906671fbbada6aea62ad33cc56608a5d881b710d Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 28 Feb 2023 14:48:31 +0100 Subject: [PATCH] Follow-up to 33496449645c8d2a1f2bd8cfb651862a86682385 Reworked handling of approximate / snug bounding boxes at Model / ModelObject / PrintObject Further optimized, so that the bounding boxes are not recalculated unnecesarilly. --- src/libslic3r/Geometry.cpp | 26 ++++++++++++++++++++++++++ src/libslic3r/Geometry.hpp | 7 +++++++ src/libslic3r/Model.cpp | 20 ++------------------ src/libslic3r/Model.hpp | 13 +++++++++++++ src/libslic3r/PrintApply.cpp | 3 ++- 5 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index ac4af48283..4b2454848f 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -918,4 +918,30 @@ double rotation_diff_z(const Transform3d &trafo_from, const Transform3d &trafo_t return atan2(vx.y(), vx.x()); } +bool trafos_differ_in_rotation_by_z_and_mirroring_by_xy_only(const Transform3d &t1, const Transform3d &t2) +{ + if (std::abs(t1.translation().z() - t2.translation().z()) > EPSILON) + // One of the object is higher than the other above the build plate (or below the build plate). + return false; + Matrix3d m1 = t1.matrix().block<3, 3>(0, 0); + Matrix3d m2 = t2.matrix().block<3, 3>(0, 0); + Matrix3d m = m2.inverse() * m1; + Vec3d z = m.block<3, 1>(0, 2); + if (std::abs(z.x()) > EPSILON || std::abs(z.y()) > EPSILON || std::abs(z.z() - 1.) > EPSILON) + // Z direction or length changed. + return false; + // Z still points in the same direction and it has the same length. + Vec3d x = m.block<3, 1>(0, 0); + Vec3d y = m.block<3, 1>(0, 1); + if (std::abs(x.z()) > EPSILON || std::abs(y.z()) > EPSILON) + return false; + double lx2 = x.squaredNorm(); + double ly2 = y.squaredNorm(); + if (lx2 - 1. > EPSILON * EPSILON || ly2 - 1. > EPSILON * EPSILON) + return false; + // Verify whether the vectors x, y are still perpendicular. + double d = x.dot(y); + return std::abs(d * d) < EPSILON * lx2 * ly2; +} + }} // namespace Slic3r::Geometry diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 1f287f6a7f..ba7e7a4b2a 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -584,6 +584,13 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation) return is_rotation_ninety_degrees(rotation.x()) && is_rotation_ninety_degrees(rotation.y()) && is_rotation_ninety_degrees(rotation.z()); } +// Returns true if one transformation may be converted into another transformation by +// rotation around Z and by mirroring in X / Y only. Two objects sharing such transformation +// may share support structures and they share Z height. +bool trafos_differ_in_rotation_by_z_and_mirroring_by_xy_only(const Transform3d &t1, const Transform3d &t2); +inline bool trafos_differ_in_rotation_by_z_and_mirroring_by_xy_only(const Transformation &t1, const Transformation &t2) + { return trafos_differ_in_rotation_by_z_and_mirroring_by_xy_only(t1.get_matrix(), t2.get_matrix()); } + template std::pair dir_to_spheric(const Vec<3, Tin> &n, Tout norm = 1.) { diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 4937416022..dec734ca13 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -643,15 +643,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->printable = rhs.printable; this->origin_translation = rhs.origin_translation; this->cut_id.copy(rhs.cut_id); - m_bounding_box_approx = rhs.m_bounding_box_approx; - m_bounding_box_approx_valid = rhs.m_bounding_box_approx_valid; - m_bounding_box_exact = rhs.m_bounding_box_exact; - m_bounding_box_exact_valid = rhs.m_bounding_box_exact_valid; - m_min_max_z_valid = rhs.m_min_max_z_valid; - m_raw_bounding_box = rhs.m_raw_bounding_box; - m_raw_bounding_box_valid = rhs.m_raw_bounding_box_valid; - m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; - m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; + this->copy_transformation_caches(rhs); this->clear_volumes(); this->volumes.reserve(rhs.volumes.size()); @@ -687,15 +679,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs) this->layer_height_profile = std::move(rhs.layer_height_profile); this->printable = std::move(rhs.printable); this->origin_translation = std::move(rhs.origin_translation); - m_bounding_box_approx = std::move(rhs.m_bounding_box_approx); - m_bounding_box_approx_valid = std::move(rhs.m_bounding_box_approx_valid); - m_bounding_box_exact = std::move(rhs.m_bounding_box_exact); - m_bounding_box_exact_valid = std::move(rhs.m_bounding_box_exact_valid); - m_min_max_z_valid = rhs.m_min_max_z_valid; - m_raw_bounding_box = rhs.m_raw_bounding_box; - m_raw_bounding_box_valid = rhs.m_raw_bounding_box_valid; - m_raw_mesh_bounding_box = rhs.m_raw_mesh_bounding_box; - m_raw_mesh_bounding_box_valid = rhs.m_raw_mesh_bounding_box_valid; + this->copy_transformation_caches(rhs); this->clear_volumes(); this->volumes = std::move(rhs.volumes); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 7ab5c2545d..08fa794810 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -606,6 +606,19 @@ private: mutable BoundingBoxf3 m_raw_mesh_bounding_box; mutable bool m_raw_mesh_bounding_box_valid { false }; + // Only use this method if now the source and dest ModelObjects are equal, for example they were synchronized by Print::apply(). + void copy_transformation_caches(const ModelObject &src) { + m_bounding_box_approx = src.m_bounding_box_approx; + m_bounding_box_approx_valid = src.m_bounding_box_approx_valid; + m_bounding_box_exact = src.m_bounding_box_exact; + m_bounding_box_exact_valid = src.m_bounding_box_exact_valid; + m_min_max_z_valid = src.m_min_max_z_valid; + m_raw_bounding_box = src.m_raw_bounding_box; + m_raw_bounding_box_valid = src.m_raw_bounding_box_valid; + m_raw_mesh_bounding_box = src.m_raw_mesh_bounding_box; + m_raw_mesh_bounding_box_valid = src.m_raw_mesh_bounding_box_valid; + } + // Called by Print::apply() to set the model pointer after making a copy. friend class Print; friend class SLAPrint; diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index e137f0157b..ae5f18fcbc 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -1250,7 +1250,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ l->get_transformation().get_matrix().isApprox(r->get_transformation().get_matrix()); })) { // If some of the instances changed, the bounding box of the updated ModelObject is likely no more valid. // This is safe as the ModelObject's bounding box is only accessed from this function, which is called from the main thread only. - model_object.invalidate_bounding_box(); // Synchronize the content of instances. auto new_instance = model_object_new.instances.begin(); for (auto old_instance = model_object.instances.begin(); old_instance != model_object.instances.end(); ++ old_instance, ++ new_instance) { @@ -1259,6 +1258,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ (*old_instance)->printable = (*new_instance)->printable; } } + // Source / dest object share the same bounding boxes, just copy them. + model_object.copy_transformation_caches(model_object_new); } }