Use shared pointers for SLA preview data

To be able to survive a sudden cancellation and subsequent cleanup in the background thread
This commit is contained in:
tamasmeszaros 2023-01-12 19:38:24 +01:00
parent bb82ce90c9
commit cf4f07c220
8 changed files with 50 additions and 39 deletions

View File

@ -1014,26 +1014,15 @@ const TriangleMesh& SLAPrintObject::pad_mesh() const
return EMPTY_MESH; return EMPTY_MESH;
} }
const TriangleMesh &SLAPrintObject::get_mesh_to_print() const const std::shared_ptr<const indexed_triangle_set> &
SLAPrintObject::get_mesh_to_print() const
{ {
const TriangleMesh *ret = nullptr;
int s = last_completed_step(); int s = last_completed_step();
if (s == slaposCount) while (s > 0 && ! m_preview_meshes[s])
ret = &EMPTY_MESH;
while (s >= 0 && !ret) {
if (!m_preview_meshes[s].empty())
ret = &m_preview_meshes[s];
--s; --s;
}
if (!ret) return m_preview_meshes[s];
ret = &EMPTY_MESH;
return *ret;
} }
std::vector<csg::CSGPart> SLAPrintObject::get_parts_to_slice() const std::vector<csg::CSGPart> SLAPrintObject::get_parts_to_slice() const

View File

@ -121,7 +121,7 @@ public:
// Get the mesh that is going to be printed with all the modifications // Get the mesh that is going to be printed with all the modifications
// like hollowing and drilled holes. // like hollowing and drilled holes.
const TriangleMesh & get_mesh_to_print() const; const std::shared_ptr<const indexed_triangle_set>& get_mesh_to_print() const;
std::vector<csg::CSGPart> get_parts_to_slice() const; std::vector<csg::CSGPart> get_parts_to_slice() const;
@ -379,7 +379,7 @@ private:
// all its holes and cavities, negatives and positive volumes unified. // all its holes and cavities, negatives and positive volumes unified.
// Essentially this should be a m_mesh_to_slice after the CSG operations // Essentially this should be a m_mesh_to_slice after the CSG operations
// or an approximation of that. // or an approximation of that.
std::array<TriangleMesh, SLAPrintObjectStep::slaposCount> m_preview_meshes; std::array<std::shared_ptr<const indexed_triangle_set>, SLAPrintObjectStep::slaposCount + 1> m_preview_meshes;
class HollowingData class HollowingData
{ {

View File

@ -228,7 +228,11 @@ void SLAPrint::Steps::generate_preview(SLAPrintObject &po, SLAPrintObjectStep st
handled = true; handled = true;
} else if (step == slaposDrillHoles && is_pure_model) { } else if (step == slaposDrillHoles && is_pure_model) {
if (po.m_model_object->sla_drain_holes.empty()) { 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; handled = true;
} else if (can_hollow) { } else if (can_hollow) {
m = csgmesh_merge_positive_parts(r); 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); 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<const indexed_triangle_set>(std::move(m));
for (size_t i = size_t(step) + 1; i < slaposCount; ++i) 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 supports are disabled, we can skip the model scan.
if(!po.m_config.supports_enable.getBool()) return; 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 = po.m_supportdata =
std::make_unique<SLAPrintObject::SupportData>( std::make_unique<SLAPrintObject::SupportData>(*meshp);
po.get_mesh_to_print() }
);
po.m_supportdata->input.zoffset = csgmesh_positive_bb(po.m_mesh_to_slice) po.m_supportdata->input.zoffset = csgmesh_positive_bb(po.m_mesh_to_slice)
.min.z(); .min.z();
@ -750,11 +759,12 @@ void SLAPrint::Steps::generate_pad(SLAPrintObject &po) {
// repeated) // repeated)
if(po.m_config.pad_enable.getBool()) { 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 = po.m_supportdata =
std::make_unique<SLAPrintObject::SupportData>( std::make_unique<SLAPrintObject::SupportData>(*meshp);
po.get_mesh_to_print() }
);
// Get the distilled pad configuration from the config // Get the distilled pad configuration from the config
// (Again, despite it was retrieved in the previous step. Note that // (Again, despite it was retrieved in the previous step. Note that

View File

@ -6628,7 +6628,7 @@ void GLCanvas3D::_load_sla_shells()
return; return;
auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance, 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)); m_volumes.volumes.emplace_back(new GLVolume(color));
GLVolume& v = *m_volumes.volumes.back(); GLVolume& v = *m_volumes.volumes.back();
#if ENABLE_SMOOTH_NORMALS #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_offset(unscale(instance.shift.x(), instance.shift.y(), 0.0));
v.set_instance_rotation({ 0.0, 0.0, (double)instance.rotation }); v.set_instance_rotation({ 0.0, 0.0, (double)instance.rotation });
v.set_instance_mirror(X, object.is_left_handed() ? -1. : 1.); 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 // adds objects' volumes
for (const SLAPrintObject* obj : print->objects()) { for (const SLAPrintObject* obj : print->objects()) {
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size(); unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
for (const SLAPrintObject::Instance& instance : obj->instances()) { for (const SLAPrintObject::Instance& instance : obj->instances()) {
auto & m = obj->get_mesh_to_print(); std::shared_ptr<const indexed_triangle_set> m = obj->get_mesh_to_print();
if (!m.empty()) { if (m && !m->empty()) {
add_volume(*obj, 0, instance, m, GLVolume::MODEL_COLOR[0], true); 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 // 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. // through the update_volumes_colors_by_extruder() call.
m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id(); 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); 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); add_volume(*obj, -int(slaposPad), instance, pad_mesh, GLVolume::SLA_PAD_COLOR, false);
} }
} }

View File

@ -55,7 +55,8 @@ void GLGizmoHollow::data_changed()
} }
const SLAPrintObject* po = m_c->selection_info()->print_object(); const SLAPrintObject* po = m_c->selection_info()->print_object();
if (po != nullptr && po->get_mesh_to_print().empty()) std::shared_ptr<const indexed_triangle_set> preview_mesh_ptr = po->get_mesh_to_print();
if (po != nullptr && (!preview_mesh_ptr || preview_mesh_ptr->empty()))
reslice_until_step(slaposAssembly); reslice_until_step(slaposAssembly);
update_volumes(); update_volumes();

View File

@ -48,7 +48,11 @@ void GLGizmoSlaBase::update_volumes()
m_input_enabled = false; m_input_enabled = false;
TriangleMesh backend_mesh = po->get_mesh_to_print(); TriangleMesh backend_mesh;
std::shared_ptr<const indexed_triangle_set> preview_mesh_ptr = po->get_mesh_to_print();
if (preview_mesh_ptr)
backend_mesh = TriangleMesh{*preview_mesh_ptr};
if (!backend_mesh.empty()) { if (!backend_mesh.empty()) {
// The backend has generated a valid mesh. Use it // The backend has generated a valid mesh. Use it
backend_mesh.transform(po->trafo().inverse()); backend_mesh.transform(po->trafo().inverse());

View File

@ -261,7 +261,10 @@ void Raycaster::on_update()
// For sla printers we use the mesh generated by the backend // For sla printers we use the mesh generated by the backend
const SLAPrintObject* po = get_pool()->selection_info()->print_object(); const SLAPrintObject* po = get_pool()->selection_info()->print_object();
assert(po != nullptr); assert(po != nullptr);
m_sla_mesh_cache = po->get_mesh_to_print(); std::shared_ptr<const indexed_triangle_set> 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()) { if (!m_sla_mesh_cache.empty()) {
m_sla_mesh_cache.transform(po->trafo().inverse()); m_sla_mesh_cache.transform(po->trafo().inverse());
meshes.emplace_back(&m_sla_mesh_cache); meshes.emplace_back(&m_sla_mesh_cache);

View File

@ -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()); 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); mesh = mesh_to_export_fff(mo, instance_id);
else { else {
const Transform3d mesh_trafo_inv = object->trafo().inverse(); 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); inst_mesh.merge(inst_supports_mesh);
} }
TriangleMesh inst_object_mesh = object->get_mesh_to_print(); std::shared_ptr<const indexed_triangle_set> 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(mesh_trafo_inv);
inst_object_mesh.transform(inst_transform, is_left_handed); inst_object_mesh.transform(inst_transform, is_left_handed);