diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3595276af..159a9693d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -54,6 +54,10 @@ #include "libslic3r/ClipperUtils.hpp" #include "libslic3r/miniz_extension.hpp" +// For stl export +#include "libslic3r/CSGMesh/ModelToCSGMesh.hpp" +#include "libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp" + #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" @@ -6382,14 +6386,34 @@ void Plater::export_stl_obj(bool extended, bool selection_only) return; // Following lambda generates a combined mesh for export with normals pointing outwards. - auto mesh_to_export_fff = [](const ModelObject& mo, int instance_id) { + auto mesh_to_export_fff = [this](const ModelObject& mo, int instance_id) { TriangleMesh mesh; - for (const ModelVolume* v : mo.volumes) - if (v->is_model_part()) { - TriangleMesh vol_mesh(v->mesh()); - vol_mesh.transform(v->get_matrix(), true); - mesh.merge(vol_mesh); - } + + std::vector csgmesh; + csgmesh.reserve(2 * mo.volumes.size()); + csg::model_to_csgmesh(mo, Transform3d::Identity(), std::back_inserter(csgmesh), + csg::mpartsPositive | csg::mpartsNegative | csg::mpartsDoSplits); + + if (csg::check_csgmesh_booleans(range(csgmesh)) == csgmesh.end()) { + try { + auto cgalm = csg::perform_csgmesh_booleans(range(csgmesh)); + mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*cgalm); + } catch (...) {} + } + + if (mesh.empty()) { + get_notification_manager()->push_plater_error_notification( + _u8L("Unable to perform boolean operation on model meshes. " + "Only positive parts will be exported.")); + + for (const ModelVolume* v : mo.volumes) + if (v->is_model_part()) { + TriangleMesh vol_mesh(v->mesh()); + vol_mesh.transform(v->get_matrix(), true); + mesh.merge(vol_mesh); + } + } + if (instance_id == -1) { TriangleMesh vols_mesh(mesh); mesh = TriangleMesh();