diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index ac4cd73ef..6b16855e8 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -593,6 +593,8 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->origin_translation = rhs.origin_translation; m_bounding_box = rhs.m_bounding_box; m_bounding_box_valid = rhs.m_bounding_box_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; @@ -627,6 +629,8 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs) this->origin_translation = std::move(rhs.origin_translation); m_bounding_box = std::move(rhs.m_bounding_box); m_bounding_box_valid = std::move(rhs.m_bounding_box_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; @@ -859,7 +863,7 @@ TriangleMesh ModelObject::full_raw_mesh() const return mesh; } -BoundingBoxf3 ModelObject::raw_mesh_bounding_box() const +const BoundingBoxf3& ModelObject::raw_mesh_bounding_box() const { if (! m_raw_mesh_bounding_box_valid) { m_raw_mesh_bounding_box_valid = true; @@ -880,33 +884,36 @@ BoundingBoxf3 ModelObject::full_raw_mesh_bounding_box() const } // A transformed snug bounding box around the non-modifier object volumes, without the translation applied. -// This bounding box is only used for the actual slicing. -BoundingBoxf3 ModelObject::raw_bounding_box() const +// This bounding box is only used for the actual slicing and for layer editing UI to calculate the layers. +const BoundingBoxf3& ModelObject::raw_bounding_box() const { - BoundingBoxf3 bb; -#if ENABLE_GENERIC_SUBPARTS_PLACEMENT - if (this->instances.empty()) - throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); + if (! m_raw_bounding_box_valid) { + m_raw_bounding_box_valid = true; + m_raw_bounding_box.reset(); + #if ENABLE_GENERIC_SUBPARTS_PLACEMENT + if (this->instances.empty()) + throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); - const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true); -#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT - for (const ModelVolume *v : this->volumes) - if (v->is_model_part()) { -#if !ENABLE_GENERIC_SUBPARTS_PLACEMENT - if (this->instances.empty()) - throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); -#endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT + const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true); + #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT + for (const ModelVolume *v : this->volumes) + if (v->is_model_part()) { + #if !ENABLE_GENERIC_SUBPARTS_PLACEMENT + if (this->instances.empty()) + throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); + #endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT -#if ENABLE_GENERIC_SUBPARTS_PLACEMENT - bb.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix())); -#else - // unmaintaned - assert(false); - // vol_mesh.transform(v->get_matrix()); - // bb.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true)); -#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT - } - return bb; + #if ENABLE_GENERIC_SUBPARTS_PLACEMENT + m_raw_bounding_box.merge(v->mesh.transformed_bounding_box(inst_matrix * v->get_matrix())); + #else + // unmaintaned + assert(false); + // vol_mesh.transform(v->get_matrix()); + // m_raw_bounding_box_valid.merge(this->instances.front()->transform_mesh_bounding_box(vol_mesh, true)); + #endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT + } + } + return m_raw_bounding_box; } // This returns an accurate snug bounding box of the transformed object instance, without the translation applied. diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 951401243..1234102e0 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -212,7 +212,7 @@ public: // This bounding box is approximate and not snug. // This bounding box is being cached. const BoundingBoxf3& bounding_box() const; - void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } + void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } // A mesh containing all transformed instances of this object. TriangleMesh mesh() const; @@ -223,11 +223,11 @@ public: TriangleMesh full_raw_mesh() const; // A transformed snug bounding box around the non-modifier object volumes, without the translation applied. // This bounding box is only used for the actual slicing. - BoundingBoxf3 raw_bounding_box() const; + const BoundingBoxf3& raw_bounding_box() const; // A snug bounding box around the transformed non-modifier object volumes. BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const; // A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes. - BoundingBoxf3 raw_mesh_bounding_box() const; + const BoundingBoxf3& raw_mesh_bounding_box() const; // A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes. BoundingBoxf3 full_raw_mesh_bounding_box() const; @@ -285,7 +285,7 @@ protected: private: ModelObject(Model *model) : m_model(model), origin_translation(Vec3d::Zero()), - m_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {} + m_bounding_box_valid(false), m_raw_bounding_box_valid(false), m_raw_mesh_bounding_box_valid(false) {} ~ModelObject(); /* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */ @@ -304,6 +304,8 @@ private: // Bounding box, cached. mutable BoundingBoxf3 m_bounding_box; mutable bool m_bounding_box_valid; + mutable BoundingBoxf3 m_raw_bounding_box; + mutable bool m_raw_bounding_box_valid; mutable BoundingBoxf3 m_raw_mesh_bounding_box; mutable bool m_raw_mesh_bounding_box_valid; }; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 9e97ab20c..b566eaded 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -132,7 +132,7 @@ public: // The slicing parameters are dependent on various configuration values // (layer height, first layer height, raft settings, print nozzle diameter etc). const SlicingParameters& slicing_parameters() const { return m_slicing_params; } - static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object); + static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z); // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions) std::vector object_extruders() const; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 954e583f7..0b51f36ec 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1370,7 +1370,7 @@ void PrintObject::update_slicing_parameters() this->print()->config(), m_config, unscale(this->size(2)), this->object_extruders()); } -SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object) +SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z) { PrintConfig print_config; PrintObjectConfig object_config; @@ -1390,7 +1390,9 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full object_extruders); sort_remove_duplicates(object_extruders); - return SlicingParameters::create_from_config(print_config, object_config, model_object.bounding_box().max.z(), object_extruders); + if (object_max_z <= 0.f) + object_max_z = model_object.raw_bounding_box().size().z(); + return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders); } // returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index fe3f0765c..0dc3ec83a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -255,16 +255,21 @@ void GLCanvas3D::LayersEditing::set_config(const DynamicPrintConfig* config) void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id) { const ModelObject *model_object_new = (object_id >= 0) ? model.objects[object_id] : nullptr; - if (model_object_new == nullptr || this->last_object_id != object_id || m_model_object != model_object_new || m_model_object->id() != model_object_new->id()) { + // Maximum height of an object changes when the object gets rotated or scaled. + // Changing maximum height of an object will invalidate the layer heigth editing profile. + // m_model_object->raw_bounding_box() is cached, therefore it is cheap even if this method is called frequently. + float new_max_z = (m_model_object == nullptr) ? 0.f : m_model_object->raw_bounding_box().size().z(); + if (m_model_object != model_object_new || this->last_object_id != object_id || m_object_max_z != new_max_z || + (model_object_new != nullptr && m_model_object->id() != model_object_new->id())) { m_layer_height_profile.clear(); m_layer_height_profile_modified = false; delete m_slicing_parameters; - m_slicing_parameters = nullptr; + m_slicing_parameters = nullptr; m_layers_texture.valid = false; + this->last_object_id = object_id; + m_model_object = model_object_new; + m_object_max_z = new_max_z; } - this->last_object_id = object_id; - m_model_object = model_object_new; - m_object_max_z = (m_model_object == nullptr) ? 0.f : m_model_object->bounding_box().max.z(); } bool GLCanvas3D::LayersEditing::is_allowed() const @@ -623,7 +628,7 @@ void GLCanvas3D::LayersEditing::update_slicing_parameters() { if (m_slicing_parameters == nullptr) { m_slicing_parameters = new SlicingParameters(); - *m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object); + *m_slicing_parameters = PrintObject::slicing_parameters(*m_config, *m_model_object, m_object_max_z); } }