mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 04:55:55 +08:00
SPE-1840: Rework multi-material segmentation to work directly on the Voronoi diagram without creating a copy of it.
Previous algorithms assume that they can get an invalid Voronoi diagram. Because of that, during the multi-material segmentation, a copy of the Voronoi diagram was created, and there were several attempts to fix missing vertices and edges. But as it shows, this wasn't a good enough approach and sometimes led to several issues like bleeding layers. After generalization, our approach for detection and repairs of invalid Voronoi diagrams from Arachne, we could assume that multi-material segmentation gets non-invalid Voronoi diagrams. With this assumption, we reimplement multi-materials segmentation to work directly on the Voronoi diagram. That should make multi-material segmentation more stable. So, this should fix several issues like bleeding layers. Also, memory consumption should decrease by a lot. Also, there should be some speedup of multi-materials segmentation.
This commit is contained in:
parent
24a497e445
commit
76435e7add
@ -124,7 +124,7 @@ static constexpr const char* PRINTABLE_ATTR = "printable";
|
|||||||
static constexpr const char* INSTANCESCOUNT_ATTR = "instances_count";
|
static constexpr const char* INSTANCESCOUNT_ATTR = "instances_count";
|
||||||
static constexpr const char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports";
|
static constexpr const char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports";
|
||||||
static constexpr const char* CUSTOM_SEAM_ATTR = "slic3rpe:custom_seam";
|
static constexpr const char* CUSTOM_SEAM_ATTR = "slic3rpe:custom_seam";
|
||||||
static constexpr const char* MMU_SEGMENTATION_ATTR = "slic3rpe:mmu_segmentation";
|
static constexpr const char* MM_SEGMENTATION_ATTR = "slic3rpe:mmu_segmentation";
|
||||||
|
|
||||||
static constexpr const char* KEY_ATTR = "key";
|
static constexpr const char* KEY_ATTR = "key";
|
||||||
static constexpr const char* VALUE_ATTR = "value";
|
static constexpr const char* VALUE_ATTR = "value";
|
||||||
@ -362,7 +362,7 @@ namespace Slic3r {
|
|||||||
std::vector<Vec3i> triangles;
|
std::vector<Vec3i> triangles;
|
||||||
std::vector<std::string> custom_supports;
|
std::vector<std::string> custom_supports;
|
||||||
std::vector<std::string> custom_seam;
|
std::vector<std::string> custom_seam;
|
||||||
std::vector<std::string> mmu_segmentation;
|
std::vector<std::string> mm_segmentation;
|
||||||
|
|
||||||
bool empty() { return vertices.empty() || triangles.empty(); }
|
bool empty() { return vertices.empty() || triangles.empty(); }
|
||||||
|
|
||||||
@ -371,7 +371,7 @@ namespace Slic3r {
|
|||||||
triangles.clear();
|
triangles.clear();
|
||||||
custom_supports.clear();
|
custom_supports.clear();
|
||||||
custom_seam.clear();
|
custom_seam.clear();
|
||||||
mmu_segmentation.clear();
|
mm_segmentation.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1830,7 +1830,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
|
m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
|
||||||
m_curr_object.geometry.custom_seam.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
|
m_curr_object.geometry.custom_seam.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
|
||||||
m_curr_object.geometry.mmu_segmentation.push_back(get_attribute_value_string(attributes, num_attributes, MMU_SEGMENTATION_ATTR));
|
m_curr_object.geometry.mm_segmentation.push_back(get_attribute_value_string(attributes, num_attributes, MM_SEGMENTATION_ATTR));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2320,25 +2320,25 @@ namespace Slic3r {
|
|||||||
if (has_transform)
|
if (has_transform)
|
||||||
volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
|
volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
|
||||||
|
|
||||||
// recreate custom supports, seam and mmu segmentation from previously loaded attribute
|
// recreate custom supports, seam and mm segmentation from previously loaded attribute
|
||||||
volume->supported_facets.reserve(triangles_count);
|
volume->supported_facets.reserve(triangles_count);
|
||||||
volume->seam_facets.reserve(triangles_count);
|
volume->seam_facets.reserve(triangles_count);
|
||||||
volume->mmu_segmentation_facets.reserve(triangles_count);
|
volume->mm_segmentation_facets.reserve(triangles_count);
|
||||||
for (size_t i=0; i<triangles_count; ++i) {
|
for (size_t i=0; i<triangles_count; ++i) {
|
||||||
size_t index = volume_data.first_triangle_id + i;
|
size_t index = volume_data.first_triangle_id + i;
|
||||||
assert(index < geometry.custom_supports.size());
|
assert(index < geometry.custom_supports.size());
|
||||||
assert(index < geometry.custom_seam.size());
|
assert(index < geometry.custom_seam.size());
|
||||||
assert(index < geometry.mmu_segmentation.size());
|
assert(index < geometry.mm_segmentation.size());
|
||||||
if (! geometry.custom_supports[index].empty())
|
if (! geometry.custom_supports[index].empty())
|
||||||
volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
|
volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
|
||||||
if (! geometry.custom_seam[index].empty())
|
if (! geometry.custom_seam[index].empty())
|
||||||
volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]);
|
volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]);
|
||||||
if (! geometry.mmu_segmentation[index].empty())
|
if (! geometry.mm_segmentation[index].empty())
|
||||||
volume->mmu_segmentation_facets.set_triangle_from_string(i, geometry.mmu_segmentation[index]);
|
volume->mm_segmentation_facets.set_triangle_from_string(i, geometry.mm_segmentation[index]);
|
||||||
}
|
}
|
||||||
volume->supported_facets.shrink_to_fit();
|
volume->supported_facets.shrink_to_fit();
|
||||||
volume->seam_facets.shrink_to_fit();
|
volume->seam_facets.shrink_to_fit();
|
||||||
volume->mmu_segmentation_facets.shrink_to_fit();
|
volume->mm_segmentation_facets.shrink_to_fit();
|
||||||
|
|
||||||
if (auto &es = volume_data.shape_configuration; es.has_value())
|
if (auto &es = volume_data.shape_configuration; es.has_value())
|
||||||
volume->emboss_shape = std::move(es);
|
volume->emboss_shape = std::move(es);
|
||||||
@ -3002,12 +3002,12 @@ namespace Slic3r {
|
|||||||
output_buffer += "\"";
|
output_buffer += "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mmu_painting_data_string = volume->mmu_segmentation_facets.get_triangle_as_string(i);
|
std::string mm_painting_data_string = volume->mm_segmentation_facets.get_triangle_as_string(i);
|
||||||
if (! mmu_painting_data_string.empty()) {
|
if (! mm_painting_data_string.empty()) {
|
||||||
output_buffer += " ";
|
output_buffer += " ";
|
||||||
output_buffer += MMU_SEGMENTATION_ATTR;
|
output_buffer += MM_SEGMENTATION_ATTR;
|
||||||
output_buffer += "=\"";
|
output_buffer += "=\"";
|
||||||
output_buffer += mmu_painting_data_string;
|
output_buffer += mm_painting_data_string;
|
||||||
output_buffer += "\"";
|
output_buffer += "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,11 +11,11 @@ namespace Slic3r::Geometry {
|
|||||||
|
|
||||||
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
||||||
using LinesIt = Lines::iterator;
|
using LinesIt = Lines::iterator;
|
||||||
using ColoredLinesIt = ColoredLines::iterator;
|
using ColoredLinesConstIt = ColoredLines::const_iterator;
|
||||||
|
|
||||||
// Explicit template instantiation.
|
// Explicit template instantiation.
|
||||||
template void VoronoiDiagram::construct_voronoi(LinesIt, LinesIt, bool);
|
template void VoronoiDiagram::construct_voronoi(LinesIt, LinesIt, bool);
|
||||||
template void VoronoiDiagram::construct_voronoi(ColoredLinesIt, ColoredLinesIt, bool);
|
template void VoronoiDiagram::construct_voronoi(ColoredLinesConstIt, ColoredLinesConstIt, bool);
|
||||||
template void VoronoiDiagram::construct_voronoi(PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt, bool);
|
template void VoronoiDiagram::construct_voronoi(PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt, bool);
|
||||||
|
|
||||||
template<typename SegmentIterator>
|
template<typename SegmentIterator>
|
||||||
|
@ -8,19 +8,22 @@ namespace Slic3r::Geometry {
|
|||||||
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
||||||
using LinesIt = Lines::iterator;
|
using LinesIt = Lines::iterator;
|
||||||
using ColoredLinesIt = ColoredLines::iterator;
|
using ColoredLinesIt = ColoredLines::iterator;
|
||||||
|
using ColoredLinesConstIt = ColoredLines::const_iterator;
|
||||||
|
|
||||||
// Explicit template instantiation.
|
// Explicit template instantiation.
|
||||||
template LinesIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, LinesIt, LinesIt);
|
template LinesIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, LinesIt, LinesIt);
|
||||||
template VD::SegmentIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt);
|
template VD::SegmentIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt);
|
||||||
template ColoredLinesIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, ColoredLinesIt, ColoredLinesIt);
|
template ColoredLinesIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, ColoredLinesIt, ColoredLinesIt);
|
||||||
|
template ColoredLinesConstIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, ColoredLinesConstIt, ColoredLinesConstIt);
|
||||||
template PolygonsSegmentIndexConstIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
template PolygonsSegmentIndexConstIt::reference VoronoiUtils::get_source_segment(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
||||||
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, LinesIt, LinesIt);
|
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, LinesIt, LinesIt);
|
||||||
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt);
|
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt);
|
||||||
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, ColoredLinesIt, ColoredLinesIt);
|
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, ColoredLinesIt, ColoredLinesIt);
|
||||||
|
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, ColoredLinesConstIt, ColoredLinesConstIt);
|
||||||
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
template Point VoronoiUtils::get_source_point(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
||||||
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, LinesIt, LinesIt);
|
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, LinesIt, LinesIt);
|
||||||
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt);
|
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, VD::SegmentIt, VD::SegmentIt);
|
||||||
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, ColoredLinesIt, ColoredLinesIt);
|
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, ColoredLinesConstIt, ColoredLinesConstIt);
|
||||||
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
template SegmentCellRange<Point> VoronoiUtils::compute_segment_cell_range(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
||||||
template Points VoronoiUtils::discretize_parabola(const Point &, const Arachne::PolygonsSegmentIndex &, const Point &, const Point &, coord_t, float);
|
template Points VoronoiUtils::discretize_parabola(const Point &, const Arachne::PolygonsSegmentIndex &, const Point &, const Point &, coord_t, float);
|
||||||
template Arachne::PolygonsPointIndex VoronoiUtils::get_source_point_index(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
template Arachne::PolygonsPointIndex VoronoiUtils::get_source_point_index(const VoronoiDiagram::cell_type &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
||||||
@ -241,7 +244,13 @@ VoronoiUtils::compute_segment_cell_range(const VD::cell_type &cell, const Segmen
|
|||||||
|
|
||||||
Vec2i64 VoronoiUtils::to_point(const VD::vertex_type *vertex)
|
Vec2i64 VoronoiUtils::to_point(const VD::vertex_type *vertex)
|
||||||
{
|
{
|
||||||
const double x = vertex->x(), y = vertex->y();
|
assert(vertex != nullptr);
|
||||||
|
return VoronoiUtils::to_point(*vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2i64 VoronoiUtils::to_point(const VD::vertex_type &vertex)
|
||||||
|
{
|
||||||
|
const double x = vertex.x(), y = vertex.y();
|
||||||
|
|
||||||
assert(std::isfinite(x) && std::isfinite(y));
|
assert(std::isfinite(x) && std::isfinite(y));
|
||||||
assert(is_in_range<int64_t>(x) && is_in_range<int64_t>(y));
|
assert(is_in_range<int64_t>(x) && is_in_range<int64_t>(y));
|
||||||
|
@ -29,6 +29,8 @@ class VoronoiUtils
|
|||||||
public:
|
public:
|
||||||
static Vec2i64 to_point(const VD::vertex_type *vertex);
|
static Vec2i64 to_point(const VD::vertex_type *vertex);
|
||||||
|
|
||||||
|
static Vec2i64 to_point(const VD::vertex_type &vertex);
|
||||||
|
|
||||||
static bool is_finite(const VD::vertex_type &vertex);
|
static bool is_finite(const VD::vertex_type &vertex);
|
||||||
|
|
||||||
static VD::vertex_type make_rotated_vertex(VD::vertex_type &vertex, double angle);
|
static VD::vertex_type make_rotated_vertex(VD::vertex_type &vertex, double angle);
|
||||||
|
@ -19,12 +19,12 @@ namespace Slic3r::Geometry {
|
|||||||
|
|
||||||
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
||||||
using LinesIt = Lines::iterator;
|
using LinesIt = Lines::iterator;
|
||||||
using ColoredLinesIt = ColoredLines::iterator;
|
using ColoredLinesConstIt = ColoredLines::const_iterator;
|
||||||
|
|
||||||
// Explicit template instantiation.
|
// Explicit template instantiation.
|
||||||
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, LinesIt, LinesIt);
|
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, LinesIt, LinesIt);
|
||||||
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, VD::SegmentIt, VD::SegmentIt);
|
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, VD::SegmentIt, VD::SegmentIt);
|
||||||
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, ColoredLinesIt, ColoredLinesIt);
|
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, ColoredLinesConstIt, ColoredLinesConstIt);
|
||||||
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
template bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &, PolygonsSegmentIndexConstIt, PolygonsSegmentIndexConstIt);
|
||||||
|
|
||||||
// The tangent vector of the parabola is computed based on the Proof of the reflective property.
|
// The tangent vector of the parabola is computed based on the Proof of the reflective property.
|
||||||
|
@ -1237,7 +1237,7 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, ConversionType con
|
|||||||
|
|
||||||
vol->supported_facets.assign(volume->supported_facets);
|
vol->supported_facets.assign(volume->supported_facets);
|
||||||
vol->seam_facets.assign(volume->seam_facets);
|
vol->seam_facets.assign(volume->seam_facets);
|
||||||
vol->mmu_segmentation_facets.assign(volume->mmu_segmentation_facets);
|
vol->mm_segmentation_facets.assign(volume->mm_segmentation_facets);
|
||||||
|
|
||||||
// Perform conversion only if the target "imperial" state is different from the current one.
|
// Perform conversion only if the target "imperial" state is different from the current one.
|
||||||
// This check supports conversion of "mixed" set of volumes, each with different "imperial" state.
|
// This check supports conversion of "mixed" set of volumes, each with different "imperial" state.
|
||||||
@ -1349,7 +1349,7 @@ void ModelVolume::reset_extra_facets()
|
|||||||
{
|
{
|
||||||
this->supported_facets.reset();
|
this->supported_facets.reset();
|
||||||
this->seam_facets.reset();
|
this->seam_facets.reset();
|
||||||
this->mmu_segmentation_facets.reset();
|
this->mm_segmentation_facets.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1915,7 +1915,7 @@ void ModelVolume::assign_new_unique_ids_recursive()
|
|||||||
config.set_new_unique_id();
|
config.set_new_unique_id();
|
||||||
supported_facets.set_new_unique_id();
|
supported_facets.set_new_unique_id();
|
||||||
seam_facets.set_new_unique_id();
|
seam_facets.set_new_unique_id();
|
||||||
mmu_segmentation_facets.set_new_unique_id();
|
mm_segmentation_facets.set_new_unique_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelVolume::rotate(double angle, Axis axis)
|
void ModelVolume::rotate(double angle, Axis axis)
|
||||||
@ -2224,7 +2224,7 @@ bool model_mmu_segmentation_data_changed(const ModelObject& mo, const ModelObjec
|
|||||||
{
|
{
|
||||||
return model_property_changed(mo, mo_new,
|
return model_property_changed(mo, mo_new,
|
||||||
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
||||||
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.mmu_segmentation_facets.timestamp_matches(mv_new.mmu_segmentation_facets); });
|
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.mm_segmentation_facets.timestamp_matches(mv_new.mm_segmentation_facets); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool model_has_parameter_modifiers_in_objects(const Model &model)
|
bool model_has_parameter_modifiers_in_objects(const Model &model)
|
||||||
|
@ -823,8 +823,8 @@ public:
|
|||||||
// List of seam enforcers/blockers.
|
// List of seam enforcers/blockers.
|
||||||
FacetsAnnotation seam_facets;
|
FacetsAnnotation seam_facets;
|
||||||
|
|
||||||
// List of mesh facets painted for MMU segmentation.
|
// List of mesh facets painted for MM segmentation.
|
||||||
FacetsAnnotation mmu_segmentation_facets;
|
FacetsAnnotation mm_segmentation_facets;
|
||||||
|
|
||||||
// Is set only when volume is Embossed Text type
|
// Is set only when volume is Embossed Text type
|
||||||
// Contain information how to re-create volume
|
// Contain information how to re-create volume
|
||||||
@ -929,12 +929,12 @@ public:
|
|||||||
this->config.set_new_unique_id();
|
this->config.set_new_unique_id();
|
||||||
this->supported_facets.set_new_unique_id();
|
this->supported_facets.set_new_unique_id();
|
||||||
this->seam_facets.set_new_unique_id();
|
this->seam_facets.set_new_unique_id();
|
||||||
this->mmu_segmentation_facets.set_new_unique_id();
|
this->mm_segmentation_facets.set_new_unique_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_fdm_support_painted() const { return !this->supported_facets.empty(); }
|
bool is_fdm_support_painted() const { return !this->supported_facets.empty(); }
|
||||||
bool is_seam_painted() const { return !this->seam_facets.empty(); }
|
bool is_seam_painted() const { return !this->seam_facets.empty(); }
|
||||||
bool is_mm_painted() const { return !this->mmu_segmentation_facets.empty(); }
|
bool is_mm_painted() const { return !this->mm_segmentation_facets.empty(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Print;
|
friend class Print;
|
||||||
@ -973,11 +973,11 @@ private:
|
|||||||
assert(this->config.id().valid());
|
assert(this->config.id().valid());
|
||||||
assert(this->supported_facets.id().valid());
|
assert(this->supported_facets.id().valid());
|
||||||
assert(this->seam_facets.id().valid());
|
assert(this->seam_facets.id().valid());
|
||||||
assert(this->mmu_segmentation_facets.id().valid());
|
assert(this->mm_segmentation_facets.id().valid());
|
||||||
assert(this->id() != this->config.id());
|
assert(this->id() != this->config.id());
|
||||||
assert(this->id() != this->supported_facets.id());
|
assert(this->id() != this->supported_facets.id());
|
||||||
assert(this->id() != this->seam_facets.id());
|
assert(this->id() != this->seam_facets.id());
|
||||||
assert(this->id() != this->mmu_segmentation_facets.id());
|
assert(this->id() != this->mm_segmentation_facets.id());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,23 +1003,23 @@ private:
|
|||||||
ObjectBase(other),
|
ObjectBase(other),
|
||||||
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull),
|
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull),
|
||||||
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
|
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
|
||||||
supported_facets(other.supported_facets), seam_facets(other.seam_facets), mmu_segmentation_facets(other.mmu_segmentation_facets),
|
supported_facets(other.supported_facets), seam_facets(other.seam_facets), mm_segmentation_facets(other.mm_segmentation_facets),
|
||||||
cut_info(other.cut_info), text_configuration(other.text_configuration), emboss_shape(other.emboss_shape)
|
cut_info(other.cut_info), text_configuration(other.text_configuration), emboss_shape(other.emboss_shape)
|
||||||
{
|
{
|
||||||
assert(this->id().valid());
|
assert(this->id().valid());
|
||||||
assert(this->config.id().valid());
|
assert(this->config.id().valid());
|
||||||
assert(this->supported_facets.id().valid());
|
assert(this->supported_facets.id().valid());
|
||||||
assert(this->seam_facets.id().valid());
|
assert(this->seam_facets.id().valid());
|
||||||
assert(this->mmu_segmentation_facets.id().valid());
|
assert(this->mm_segmentation_facets.id().valid());
|
||||||
assert(this->id() != this->config.id());
|
assert(this->id() != this->config.id());
|
||||||
assert(this->id() != this->supported_facets.id());
|
assert(this->id() != this->supported_facets.id());
|
||||||
assert(this->id() != this->seam_facets.id());
|
assert(this->id() != this->seam_facets.id());
|
||||||
assert(this->id() != this->mmu_segmentation_facets.id());
|
assert(this->id() != this->mm_segmentation_facets.id());
|
||||||
assert(this->id() == other.id());
|
assert(this->id() == other.id());
|
||||||
assert(this->config.id() == other.config.id());
|
assert(this->config.id() == other.config.id());
|
||||||
assert(this->supported_facets.id() == other.supported_facets.id());
|
assert(this->supported_facets.id() == other.supported_facets.id());
|
||||||
assert(this->seam_facets.id() == other.seam_facets.id());
|
assert(this->seam_facets.id() == other.seam_facets.id());
|
||||||
assert(this->mmu_segmentation_facets.id() == other.mmu_segmentation_facets.id());
|
assert(this->mm_segmentation_facets.id() == other.mm_segmentation_facets.id());
|
||||||
this->set_material_id(other.material_id());
|
this->set_material_id(other.material_id());
|
||||||
}
|
}
|
||||||
// Providing a new mesh, therefore this volume will get a new unique ID assigned.
|
// Providing a new mesh, therefore this volume will get a new unique ID assigned.
|
||||||
@ -1031,11 +1031,11 @@ private:
|
|||||||
assert(this->config.id().valid());
|
assert(this->config.id().valid());
|
||||||
assert(this->supported_facets.id().valid());
|
assert(this->supported_facets.id().valid());
|
||||||
assert(this->seam_facets.id().valid());
|
assert(this->seam_facets.id().valid());
|
||||||
assert(this->mmu_segmentation_facets.id().valid());
|
assert(this->mm_segmentation_facets.id().valid());
|
||||||
assert(this->id() != this->config.id());
|
assert(this->id() != this->config.id());
|
||||||
assert(this->id() != this->supported_facets.id());
|
assert(this->id() != this->supported_facets.id());
|
||||||
assert(this->id() != this->seam_facets.id());
|
assert(this->id() != this->seam_facets.id());
|
||||||
assert(this->id() != this->mmu_segmentation_facets.id());
|
assert(this->id() != this->mm_segmentation_facets.id());
|
||||||
assert(this->id() != other.id());
|
assert(this->id() != other.id());
|
||||||
assert(this->config.id() == other.config.id());
|
assert(this->config.id() == other.config.id());
|
||||||
this->set_material_id(other.material_id());
|
this->set_material_id(other.material_id());
|
||||||
@ -1046,11 +1046,11 @@ private:
|
|||||||
assert(this->config.id() != other.config.id());
|
assert(this->config.id() != other.config.id());
|
||||||
assert(this->supported_facets.id() != other.supported_facets.id());
|
assert(this->supported_facets.id() != other.supported_facets.id());
|
||||||
assert(this->seam_facets.id() != other.seam_facets.id());
|
assert(this->seam_facets.id() != other.seam_facets.id());
|
||||||
assert(this->mmu_segmentation_facets.id() != other.mmu_segmentation_facets.id());
|
assert(this->mm_segmentation_facets.id() != other.mm_segmentation_facets.id());
|
||||||
assert(this->id() != this->config.id());
|
assert(this->id() != this->config.id());
|
||||||
assert(this->supported_facets.empty());
|
assert(this->supported_facets.empty());
|
||||||
assert(this->seam_facets.empty());
|
assert(this->seam_facets.empty());
|
||||||
assert(this->mmu_segmentation_facets.empty());
|
assert(this->mm_segmentation_facets.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume& operator=(ModelVolume &rhs) = delete;
|
ModelVolume& operator=(ModelVolume &rhs) = delete;
|
||||||
@ -1058,19 +1058,19 @@ private:
|
|||||||
friend class cereal::access;
|
friend class cereal::access;
|
||||||
friend class UndoRedo::StackImpl;
|
friend class UndoRedo::StackImpl;
|
||||||
// Used for deserialization, therefore no IDs are allocated.
|
// Used for deserialization, therefore no IDs are allocated.
|
||||||
ModelVolume() : ObjectBase(-1), config(-1), supported_facets(-1), seam_facets(-1), mmu_segmentation_facets(-1), object(nullptr) {
|
ModelVolume() : ObjectBase(-1), config(-1), supported_facets(-1), seam_facets(-1), mm_segmentation_facets(-1), object(nullptr) {
|
||||||
assert(this->id().invalid());
|
assert(this->id().invalid());
|
||||||
assert(this->config.id().invalid());
|
assert(this->config.id().invalid());
|
||||||
assert(this->supported_facets.id().invalid());
|
assert(this->supported_facets.id().invalid());
|
||||||
assert(this->seam_facets.id().invalid());
|
assert(this->seam_facets.id().invalid());
|
||||||
assert(this->mmu_segmentation_facets.id().invalid());
|
assert(this->mm_segmentation_facets.id().invalid());
|
||||||
}
|
}
|
||||||
template<class Archive> void load(Archive &ar) {
|
template<class Archive> void load(Archive &ar) {
|
||||||
bool has_convex_hull;
|
bool has_convex_hull;
|
||||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, cut_info);
|
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, cut_info);
|
||||||
cereal::load_by_value(ar, supported_facets);
|
cereal::load_by_value(ar, supported_facets);
|
||||||
cereal::load_by_value(ar, seam_facets);
|
cereal::load_by_value(ar, seam_facets);
|
||||||
cereal::load_by_value(ar, mmu_segmentation_facets);
|
cereal::load_by_value(ar, mm_segmentation_facets);
|
||||||
cereal::load_by_value(ar, config);
|
cereal::load_by_value(ar, config);
|
||||||
cereal::load(ar, text_configuration);
|
cereal::load(ar, text_configuration);
|
||||||
cereal::load(ar, emboss_shape);
|
cereal::load(ar, emboss_shape);
|
||||||
@ -1088,7 +1088,7 @@ private:
|
|||||||
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, cut_info);
|
ar(name, source, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull, cut_info);
|
||||||
cereal::save_by_value(ar, supported_facets);
|
cereal::save_by_value(ar, supported_facets);
|
||||||
cereal::save_by_value(ar, seam_facets);
|
cereal::save_by_value(ar, seam_facets);
|
||||||
cereal::save_by_value(ar, mmu_segmentation_facets);
|
cereal::save_by_value(ar, mm_segmentation_facets);
|
||||||
cereal::save_by_value(ar, config);
|
cereal::save_by_value(ar, config);
|
||||||
cereal::save(ar, text_configuration);
|
cereal::save(ar, text_configuration);
|
||||||
cereal::save(ar, emboss_shape);
|
cereal::save(ar, emboss_shape);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -78,8 +78,8 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst,
|
|||||||
mv_dst.supported_facets.assign(mv_src.supported_facets);
|
mv_dst.supported_facets.assign(mv_src.supported_facets);
|
||||||
assert(mv_dst.seam_facets.id() == mv_src.seam_facets.id());
|
assert(mv_dst.seam_facets.id() == mv_src.seam_facets.id());
|
||||||
mv_dst.seam_facets.assign(mv_src.seam_facets);
|
mv_dst.seam_facets.assign(mv_src.seam_facets);
|
||||||
assert(mv_dst.mmu_segmentation_facets.id() == mv_src.mmu_segmentation_facets.id());
|
assert(mv_dst.mm_segmentation_facets.id() == mv_src.mm_segmentation_facets.id());
|
||||||
mv_dst.mmu_segmentation_facets.assign(mv_src.mmu_segmentation_facets);
|
mv_dst.mm_segmentation_facets.assign(mv_src.mm_segmentation_facets);
|
||||||
//FIXME what to do with the materials?
|
//FIXME what to do with the materials?
|
||||||
// mv_dst.m_material_id = mv_src.m_material_id;
|
// mv_dst.m_material_id = mv_src.m_material_id;
|
||||||
++ i_src;
|
++ i_src;
|
||||||
@ -1374,7 +1374,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
std::vector<unsigned int> painting_extruders;
|
std::vector<unsigned int> painting_extruders;
|
||||||
if (const auto &volumes = print_object.model_object()->volumes;
|
if (const auto &volumes = print_object.model_object()->volumes;
|
||||||
num_extruders > 1 &&
|
num_extruders > 1 &&
|
||||||
std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume *v) { return ! v->mmu_segmentation_facets.empty(); }) != volumes.end()) {
|
std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume *v) { return ! v->mm_segmentation_facets.empty(); }) != volumes.end()) {
|
||||||
//FIXME be more specific! Don't enumerate extruders that are not used for painting!
|
//FIXME be more specific! Don't enumerate extruders that are not used for painting!
|
||||||
painting_extruders.assign(num_extruders, 0);
|
painting_extruders.assign(num_extruders, 0);
|
||||||
std::iota(painting_extruders.begin(), painting_extruders.end(), 1);
|
std::iota(painting_extruders.begin(), painting_extruders.end(), 1);
|
||||||
|
@ -728,7 +728,7 @@ void PrintObject::slice_volumes()
|
|||||||
// Is any ModelVolume MMU painted?
|
// Is any ModelVolume MMU painted?
|
||||||
if (const auto& volumes = this->model_object()->volumes;
|
if (const auto& volumes = this->model_object()->volumes;
|
||||||
m_print->config().nozzle_diameter.size() > 1 &&
|
m_print->config().nozzle_diameter.size() > 1 &&
|
||||||
std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume* v) { return !v->mmu_segmentation_facets.empty(); }) != volumes.end()) {
|
std::find_if(volumes.begin(), volumes.end(), [](const ModelVolume* v) { return !v->mm_segmentation_facets.empty(); }) != volumes.end()) {
|
||||||
|
|
||||||
// If XY Size compensation is also enabled, notify the user that XY Size compensation
|
// If XY Size compensation is also enabled, notify the user that XY Size compensation
|
||||||
// would not be used because the object is multi-material painted.
|
// would not be used because the object is multi-material painted.
|
||||||
|
@ -4922,7 +4922,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||||||
for (GLVolume *vol : visible_volumes) {
|
for (GLVolume *vol : visible_volumes) {
|
||||||
const int obj_idx = vol->object_idx();
|
const int obj_idx = vol->object_idx();
|
||||||
const int vol_idx = vol->volume_idx();
|
const int vol_idx = vol->volume_idx();
|
||||||
const bool render_as_painted = is_enabled_painted_thumbnail && obj_idx >= 0 && vol_idx >= 0 && !model_objects[obj_idx]->volumes[vol_idx]->mmu_segmentation_facets.empty();
|
const bool render_as_painted = is_enabled_painted_thumbnail && obj_idx >= 0 && vol_idx >= 0 && !model_objects[obj_idx]->volumes[vol_idx]->mm_segmentation_facets.empty();
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader(render_as_painted ? "mm_gouraud" : "gouraud_light");
|
GLShaderProgram* shader = wxGetApp().get_shader(render_as_painted ? "mm_gouraud" : "gouraud_light");
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
continue;
|
continue;
|
||||||
@ -4958,7 +4958,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||||||
const ModelVolume& model_volume = *model_objects[obj_idx]->volumes[vol_idx];
|
const ModelVolume& model_volume = *model_objects[obj_idx]->volumes[vol_idx];
|
||||||
const size_t extruder_idx = get_extruder_color_idx(model_volume, extruders_count);
|
const size_t extruder_idx = get_extruder_color_idx(model_volume, extruders_count);
|
||||||
TriangleSelectorMmGui ts(model_volume.mesh(), extruders_colors, extruders_colors[extruder_idx]);
|
TriangleSelectorMmGui ts(model_volume.mesh(), extruders_colors, extruders_colors[extruder_idx]);
|
||||||
ts.deserialize(model_volume.mmu_segmentation_facets.get_data(), true);
|
ts.deserialize(model_volume.mm_segmentation_facets.get_data(), true);
|
||||||
ts.request_update_render_data();
|
ts.request_update_render_data();
|
||||||
|
|
||||||
ts.render(nullptr, model_matrix);
|
ts.render(nullptr, model_matrix);
|
||||||
|
@ -1905,7 +1905,7 @@ void ObjectList::del_info_item(const int obj_idx, InfoItemType type)
|
|||||||
cnv->get_gizmos_manager().reset_all_states();
|
cnv->get_gizmos_manager().reset_all_states();
|
||||||
Plater::TakeSnapshot(plater, _L("Remove Multi Material painting"));
|
Plater::TakeSnapshot(plater, _L("Remove Multi Material painting"));
|
||||||
for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
|
for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
|
||||||
mv->mmu_segmentation_facets.reset();
|
mv->mm_segmentation_facets.reset();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InfoItemType::Sinking:
|
case InfoItemType::Sinking:
|
||||||
@ -2897,7 +2897,7 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
|
|||||||
[type](const ModelVolume *mv) {
|
[type](const ModelVolume *mv) {
|
||||||
return !(type == InfoItemType::CustomSupports ? mv->supported_facets.empty() :
|
return !(type == InfoItemType::CustomSupports ? mv->supported_facets.empty() :
|
||||||
type == InfoItemType::CustomSeam ? mv->seam_facets.empty() :
|
type == InfoItemType::CustomSeam ? mv->seam_facets.empty() :
|
||||||
mv->mmu_segmentation_facets.empty());
|
mv->mm_segmentation_facets.empty());
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -648,7 +648,7 @@ void Preview::update_layers_slider_mode()
|
|||||||
if ((volume->config.has("extruder") &&
|
if ((volume->config.has("extruder") &&
|
||||||
volume->config.option("extruder")->getInt() != 0 && // extruder isn't default
|
volume->config.option("extruder")->getInt() != 0 && // extruder isn't default
|
||||||
volume->config.option("extruder")->getInt() != extruder) ||
|
volume->config.option("extruder")->getInt() != extruder) ||
|
||||||
!volume->mmu_segmentation_facets.empty())
|
!volume->mm_segmentation_facets.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (const auto& range : object->layer_config_ranges)
|
for (const auto& range : object->layer_config_ranges)
|
||||||
|
@ -517,7 +517,7 @@ void GLGizmoMmuSegmentation::update_model_object() const
|
|||||||
if (! mv->is_model_part())
|
if (! mv->is_model_part())
|
||||||
continue;
|
continue;
|
||||||
++idx;
|
++idx;
|
||||||
updated |= mv->mmu_segmentation_facets.set(*m_triangle_selectors[idx].get());
|
updated |= mv->mm_segmentation_facets.set(*m_triangle_selectors[idx].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updated) {
|
if (updated) {
|
||||||
@ -547,7 +547,7 @@ void GLGizmoMmuSegmentation::init_model_triangle_selectors()
|
|||||||
size_t extruder_idx = get_extruder_color_idx(*mv, extruders_count);
|
size_t extruder_idx = get_extruder_color_idx(*mv, extruders_count);
|
||||||
m_triangle_selectors.emplace_back(std::make_unique<TriangleSelectorMmGui>(*mesh, m_modified_extruders_colors, m_original_extruders_colors[extruder_idx]));
|
m_triangle_selectors.emplace_back(std::make_unique<TriangleSelectorMmGui>(*mesh, m_modified_extruders_colors, m_original_extruders_colors[extruder_idx]));
|
||||||
// Reset of TriangleSelector is done inside TriangleSelectorMmGUI's constructor, so we don't need it to perform it again in deserialize().
|
// Reset of TriangleSelector is done inside TriangleSelectorMmGUI's constructor, so we don't need it to perform it again in deserialize().
|
||||||
m_triangle_selectors.back()->deserialize(mv->mmu_segmentation_facets.get_data(), false);
|
m_triangle_selectors.back()->deserialize(mv->mm_segmentation_facets.get_data(), false);
|
||||||
m_triangle_selectors.back()->request_update_render_data();
|
m_triangle_selectors.back()->request_update_render_data();
|
||||||
}
|
}
|
||||||
m_original_volumes_extruder_idxs = get_extruder_id_for_volumes(*mo);
|
m_original_volumes_extruder_idxs = get_extruder_id_for_volumes(*mo);
|
||||||
|
@ -3702,7 +3702,7 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const
|
|||||||
// We need to make sure that the painted data point to existing triangles.
|
// We need to make sure that the painted data point to existing triangles.
|
||||||
new_volume->supported_facets.assign(old_volume->supported_facets);
|
new_volume->supported_facets.assign(old_volume->supported_facets);
|
||||||
new_volume->seam_facets.assign(old_volume->seam_facets);
|
new_volume->seam_facets.assign(old_volume->seam_facets);
|
||||||
new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets);
|
new_volume->mm_segmentation_facets.assign(old_volume->mm_segmentation_facets);
|
||||||
}
|
}
|
||||||
std::swap(old_model_object->volumes[volume_idx], old_model_object->volumes.back());
|
std::swap(old_model_object->volumes[volume_idx], old_model_object->volumes.back());
|
||||||
old_model_object->delete_volume(old_model_object->volumes.size() - 1);
|
old_model_object->delete_volume(old_model_object->volumes.size() - 1);
|
||||||
@ -7918,10 +7918,10 @@ void Plater::clear_before_change_mesh(int obj_idx, const std::string ¬ificati
|
|||||||
// may be different and they would make no sense.
|
// may be different and they would make no sense.
|
||||||
bool paint_removed = false;
|
bool paint_removed = false;
|
||||||
for (ModelVolume* mv : mo->volumes) {
|
for (ModelVolume* mv : mo->volumes) {
|
||||||
paint_removed |= ! mv->supported_facets.empty() || ! mv->seam_facets.empty() || ! mv->mmu_segmentation_facets.empty();
|
paint_removed |= ! mv->supported_facets.empty() || ! mv->seam_facets.empty() || ! mv->mm_segmentation_facets.empty();
|
||||||
mv->supported_facets.reset();
|
mv->supported_facets.reset();
|
||||||
mv->seam_facets.reset();
|
mv->seam_facets.reset();
|
||||||
mv->mmu_segmentation_facets.reset();
|
mv->mm_segmentation_facets.reset();
|
||||||
}
|
}
|
||||||
if (paint_removed) {
|
if (paint_removed) {
|
||||||
// snapshot_time is captured by copy so the lambda knows where to undo/redo to.
|
// snapshot_time is captured by copy so the lambda knows where to undo/redo to.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user