From 7e4ac102f435e39fc847c733e1b2a124da7aea14 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 28 Jan 2025 00:20:44 +0100 Subject: [PATCH] Follow-up to 963f96b - fixed crash when one of the partial meshes was degenerate (SPE-2661) --- src/libslic3r/CSGMesh/ModelToCSGMesh.hpp | 69 ++++++++++++++---------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp b/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp index 7e639cca07..2b69b1bea1 100644 --- a/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp +++ b/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp @@ -40,42 +40,57 @@ void model_to_csgmesh(const ModelObject &mo, ((do_positives && vol->is_model_part()) || (do_negatives && vol->is_negative_volume()))) { - if (do_splits && its_is_splittable(vol->mesh().its)) { - CSGPart part_begin{{}, vol->is_model_part() ? CSGType::Union : CSGType::Difference}; - part_begin.stack_operation = CSGStackOp::Push; - *out = std::move(part_begin); - ++out; - + bool attempt_split = do_splits && its_is_splittable(vol->mesh().its); + bool split_failed = false; + + if (attempt_split) { // Collect partial meshes and keep outward and inward facing meshes separately. std::vector meshes_union; std::vector meshes_difference; - its_split(vol->mesh().its, SplitOutputFn{[&meshes_union, &meshes_difference](indexed_triangle_set &&its) { + its_split(vol->mesh().its, SplitOutputFn{[&meshes_union, &meshes_difference, &split_failed](indexed_triangle_set &&its) { if (its.empty()) return; - if (its_volume(its) >= 0.f) - meshes_union.emplace_back(std::move(its)); - else { - its_flip_triangles(its); - meshes_difference.emplace_back(std::move(its)); + double volume = its_volume(its); + if (std::abs(volume) > 1.) { + if (volume > 0.) + meshes_union.emplace_back(std::move(its)); + else if (volume < 0.) { + its_flip_triangles(its); + meshes_difference.emplace_back(std::move(its)); + } + } else { + // Little mesh like that may be some degenerate artifact. + // Things like that might throw further processing off track (SPE-2661). + // Better do not split the mesh and work with it as we got it. + split_failed = true; } }}); - // Add the operation for each of the partial mesh (outward-facing normals go first). - for (auto* meshes : { &meshes_union, &meshes_difference}) { - for (indexed_triangle_set& its : *meshes) { - CSGPart part{ std::make_unique(std::move(its)), - meshes == &meshes_union ? CSGType::Union : CSGType::Difference, - (trafo * vol->get_matrix()).cast() }; - *out = std::move(part); - ++out; - } - } + if (! split_failed) { + CSGPart part_begin{{}, vol->is_model_part() ? CSGType::Union : CSGType::Difference}; + part_begin.stack_operation = CSGStackOp::Push; + *out = std::move(part_begin); + ++out; - CSGPart part_end{{}}; - part_end.stack_operation = CSGStackOp::Pop; - *out = std::move(part_end); - ++out; - } else { + // Add the operation for each of the partial mesh (outward-facing normals go first). + for (auto* meshes : { &meshes_union, &meshes_difference}) { + for (indexed_triangle_set& its : *meshes) { + CSGPart part{ std::make_unique(std::move(its)), + meshes == &meshes_union ? CSGType::Union : CSGType::Difference, + (trafo * vol->get_matrix()).cast() }; + *out = std::move(part); + ++out; + } + } + + CSGPart part_end{{}}; + part_end.stack_operation = CSGStackOp::Pop; + *out = std::move(part_end); + ++out; + } + } + + if (! attempt_split || split_failed) { CSGPart part{&(vol->mesh().its), vol->is_model_part() ? CSGType::Union : CSGType::Difference, (trafo * vol->get_matrix()).cast()};