From cf4f07c2205ce5553f8d4db36db589f56d1627d4 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 12 Jan 2023 19:38:24 +0100 Subject: [PATCH] Use shared pointers for SLA preview data To be able to survive a sudden cancellation and subsequent cleanup in the background thread --- src/libslic3r/SLAPrint.cpp | 19 ++++----------- src/libslic3r/SLAPrint.hpp | 4 ++-- src/libslic3r/SLAPrintSteps.cpp | 30 ++++++++++++++++-------- src/slic3r/GUI/GLCanvas3D.cpp | 14 +++++------ src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 3 ++- src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp | 6 ++++- src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 5 +++- src/slic3r/GUI/Plater.cpp | 8 +++++-- 8 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 79cc2605f..80857e34a 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1014,26 +1014,15 @@ const TriangleMesh& SLAPrintObject::pad_mesh() const return EMPTY_MESH; } -const TriangleMesh &SLAPrintObject::get_mesh_to_print() const +const std::shared_ptr & +SLAPrintObject::get_mesh_to_print() const { - const TriangleMesh *ret = nullptr; - int s = last_completed_step(); - if (s == slaposCount) - ret = &EMPTY_MESH; - - while (s >= 0 && !ret) { - if (!m_preview_meshes[s].empty()) - ret = &m_preview_meshes[s]; - + while (s > 0 && ! m_preview_meshes[s]) --s; - } - if (!ret) - ret = &EMPTY_MESH; - - return *ret; + return m_preview_meshes[s]; } std::vector SLAPrintObject::get_parts_to_slice() const diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index e6a4286ea..6d35f013d 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -121,7 +121,7 @@ public: // Get the mesh that is going to be printed with all the modifications // like hollowing and drilled holes. - const TriangleMesh & get_mesh_to_print() const; + const std::shared_ptr& get_mesh_to_print() const; std::vector get_parts_to_slice() const; @@ -379,7 +379,7 @@ private: // all its holes and cavities, negatives and positive volumes unified. // Essentially this should be a m_mesh_to_slice after the CSG operations // or an approximation of that. - std::array m_preview_meshes; + std::array, SLAPrintObjectStep::slaposCount + 1> m_preview_meshes; class HollowingData { diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index f3824f751..2f7243a9c 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -228,7 +228,11 @@ void SLAPrint::Steps::generate_preview(SLAPrintObject &po, SLAPrintObjectStep st handled = true; } else if (step == slaposDrillHoles && is_pure_model) { if (po.m_model_object->sla_drain_holes.empty()) { - m = po.m_preview_meshes[slaposHollowing].its; + // Get the last printable preview + auto &meshp = po.get_mesh_to_print(); + if (meshp) + m = *(meshp); + handled = true; } else if (can_hollow) { m = csgmesh_merge_positive_parts(r); @@ -286,7 +290,11 @@ void SLAPrint::Steps::generate_preview(SLAPrintObject &po, SLAPrintObjectStep st m = generate_preview_vdb(po, step); } - po.m_preview_meshes[step] = TriangleMesh{std::move(m)}; + assert(po.m_preview_meshes[step].empty()); + + if (!m.empty()) + po.m_preview_meshes[step] = + std::make_shared(std::move(m)); for (size_t i = size_t(step) + 1; i < slaposCount; ++i) { @@ -604,11 +612,12 @@ void SLAPrint::Steps::support_points(SLAPrintObject &po) // If supports are disabled, we can skip the model scan. if(!po.m_config.supports_enable.getBool()) return; - if (!po.m_supportdata) + if (!po.m_supportdata) { + auto &meshp = po.get_mesh_to_print(); + assert(meshp); po.m_supportdata = - std::make_unique( - po.get_mesh_to_print() - ); + std::make_unique(*meshp); + } po.m_supportdata->input.zoffset = csgmesh_positive_bb(po.m_mesh_to_slice) .min.z(); @@ -750,11 +759,12 @@ void SLAPrint::Steps::generate_pad(SLAPrintObject &po) { // repeated) if(po.m_config.pad_enable.getBool()) { - if (!po.m_supportdata) + if (!po.m_supportdata) { + auto &meshp = po.get_mesh_to_print(); + assert(meshp); po.m_supportdata = - std::make_unique( - po.get_mesh_to_print() - ); + std::make_unique(*meshp); + } // Get the distilled pad configuration from the config // (Again, despite it was retrieved in the previous step. Note that diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index fa94e6abf..c9eb10060 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6628,7 +6628,7 @@ void GLCanvas3D::_load_sla_shells() return; auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance, - const TriangleMesh& mesh, const ColorRGBA& color, bool outside_printer_detection_enabled) { + const indexed_triangle_set& mesh, const ColorRGBA& color, bool outside_printer_detection_enabled) { m_volumes.volumes.emplace_back(new GLVolume(color)); GLVolume& v = *m_volumes.volumes.back(); #if ENABLE_SMOOTH_NORMALS @@ -6641,22 +6641,22 @@ void GLCanvas3D::_load_sla_shells() v.set_instance_offset(unscale(instance.shift.x(), instance.shift.y(), 0.0)); v.set_instance_rotation({ 0.0, 0.0, (double)instance.rotation }); v.set_instance_mirror(X, object.is_left_handed() ? -1. : 1.); - v.set_convex_hull(mesh.convex_hull_3d()); + v.set_convex_hull(TriangleMesh{its_convex_hull(mesh)}); }; // adds objects' volumes for (const SLAPrintObject* obj : print->objects()) { unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size(); for (const SLAPrintObject::Instance& instance : obj->instances()) { - auto & m = obj->get_mesh_to_print(); - if (!m.empty()) { - add_volume(*obj, 0, instance, m, GLVolume::MODEL_COLOR[0], true); + std::shared_ptr m = obj->get_mesh_to_print(); + if (m && !m->empty()) { + add_volume(*obj, 0, instance, *m, GLVolume::MODEL_COLOR[0], true); // Set the extruder_id and volume_id to achieve the same color as in the 3D scene when // through the update_volumes_colors_by_extruder() call. m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id(); - if (auto &tree_mesh = obj->support_mesh(); !tree_mesh.empty()) + if (auto &tree_mesh = obj->support_mesh().its; !tree_mesh.empty()) add_volume(*obj, -int(slaposSupportTree), instance, tree_mesh, GLVolume::SLA_SUPPORT_COLOR, true); - if (auto &pad_mesh = obj->pad_mesh(); !pad_mesh.empty()) + if (auto &pad_mesh = obj->pad_mesh().its; !pad_mesh.empty()) add_volume(*obj, -int(slaposPad), instance, pad_mesh, GLVolume::SLA_PAD_COLOR, false); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index ec6ea0a1f..5bd2d98fd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -55,7 +55,8 @@ void GLGizmoHollow::data_changed() } const SLAPrintObject* po = m_c->selection_info()->print_object(); - if (po != nullptr && po->get_mesh_to_print().empty()) + std::shared_ptr preview_mesh_ptr = po->get_mesh_to_print(); + if (po != nullptr && (!preview_mesh_ptr || preview_mesh_ptr->empty())) reslice_until_step(slaposAssembly); update_volumes(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp index 9e94b9604..a9876bed1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp @@ -48,7 +48,11 @@ void GLGizmoSlaBase::update_volumes() m_input_enabled = false; - TriangleMesh backend_mesh = po->get_mesh_to_print(); + TriangleMesh backend_mesh; + std::shared_ptr preview_mesh_ptr = po->get_mesh_to_print(); + if (preview_mesh_ptr) + backend_mesh = TriangleMesh{*preview_mesh_ptr}; + if (!backend_mesh.empty()) { // The backend has generated a valid mesh. Use it backend_mesh.transform(po->trafo().inverse()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 62f7eb5fe..b33b0b202 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -261,7 +261,10 @@ void Raycaster::on_update() // For sla printers we use the mesh generated by the backend const SLAPrintObject* po = get_pool()->selection_info()->print_object(); assert(po != nullptr); - m_sla_mesh_cache = po->get_mesh_to_print(); + std::shared_ptr preview_mesh_ptr = po->get_mesh_to_print(); + if (preview_mesh_ptr) + m_sla_mesh_cache = TriangleMesh{*preview_mesh_ptr}; + if (!m_sla_mesh_cache.empty()) { m_sla_mesh_cache.transform(po->trafo().inverse()); meshes.emplace_back(&m_sla_mesh_cache); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index dbdd24d15..a0ed276af 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6115,7 +6115,7 @@ void Plater::export_stl_obj(bool extended, bool selection_only) const SLAPrintObject *object = this->p->sla_print.get_print_object_by_model_object_id(mo.id()); - if (object->get_mesh_to_print().empty()) + if (auto m = object->get_mesh_to_print(); !m || m->empty()) mesh = mesh_to_export_fff(mo, instance_id); else { const Transform3d mesh_trafo_inv = object->trafo().inverse(); @@ -6155,7 +6155,11 @@ void Plater::export_stl_obj(bool extended, bool selection_only) inst_mesh.merge(inst_supports_mesh); } - TriangleMesh inst_object_mesh = object->get_mesh_to_print(); + std::shared_ptr m = object->get_mesh_to_print(); + TriangleMesh inst_object_mesh; + if (m) + inst_object_mesh = TriangleMesh{*m}; + inst_object_mesh.transform(mesh_trafo_inv); inst_object_mesh.transform(inst_transform, is_left_handed);