Follow-up to 963f96b - fixed crash when one of the partial meshes was degenerate (SPE-2661)

This commit is contained in:
Lukas Matena 2025-01-28 00:20:44 +01:00
parent 9b8790e4d8
commit 7e4ac102f4

View File

@ -40,42 +40,57 @@ void model_to_csgmesh(const ModelObject &mo,
((do_positives && vol->is_model_part()) || ((do_positives && vol->is_model_part()) ||
(do_negatives && vol->is_negative_volume()))) { (do_negatives && vol->is_negative_volume()))) {
if (do_splits && its_is_splittable(vol->mesh().its)) { bool attempt_split = do_splits && its_is_splittable(vol->mesh().its);
CSGPart part_begin{{}, vol->is_model_part() ? CSGType::Union : CSGType::Difference}; bool split_failed = false;
part_begin.stack_operation = CSGStackOp::Push;
*out = std::move(part_begin); if (attempt_split) {
++out;
// Collect partial meshes and keep outward and inward facing meshes separately. // Collect partial meshes and keep outward and inward facing meshes separately.
std::vector<indexed_triangle_set> meshes_union; std::vector<indexed_triangle_set> meshes_union;
std::vector<indexed_triangle_set> meshes_difference; std::vector<indexed_triangle_set> 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()) if (its.empty())
return; return;
if (its_volume(its) >= 0.f) double volume = its_volume(its);
meshes_union.emplace_back(std::move(its)); if (std::abs(volume) > 1.) {
else { if (volume > 0.)
its_flip_triangles(its); meshes_union.emplace_back(std::move(its));
meshes_difference.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). if (! split_failed) {
for (auto* meshes : { &meshes_union, &meshes_difference}) { CSGPart part_begin{{}, vol->is_model_part() ? CSGType::Union : CSGType::Difference};
for (indexed_triangle_set& its : *meshes) { part_begin.stack_operation = CSGStackOp::Push;
CSGPart part{ std::make_unique<indexed_triangle_set>(std::move(its)), *out = std::move(part_begin);
meshes == &meshes_union ? CSGType::Union : CSGType::Difference, ++out;
(trafo * vol->get_matrix()).cast<float>() };
*out = std::move(part);
++out;
}
}
CSGPart part_end{{}}; // Add the operation for each of the partial mesh (outward-facing normals go first).
part_end.stack_operation = CSGStackOp::Pop; for (auto* meshes : { &meshes_union, &meshes_difference}) {
*out = std::move(part_end); for (indexed_triangle_set& its : *meshes) {
++out; CSGPart part{ std::make_unique<indexed_triangle_set>(std::move(its)),
} else { meshes == &meshes_union ? CSGType::Union : CSGType::Difference,
(trafo * vol->get_matrix()).cast<float>() };
*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), CSGPart part{&(vol->mesh().its),
vol->is_model_part() ? CSGType::Union : CSGType::Difference, vol->is_model_part() ? CSGType::Union : CSGType::Difference,
(trafo * vol->get_matrix()).cast<float>()}; (trafo * vol->get_matrix()).cast<float>()};