mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-11 14:59:00 +08:00
Rename EnforcerBlockerType to TriangleStateType because we no longer use it just as a blocker or an enforcer.
This commit is contained in:
parent
13e2af71e1
commit
b425fe459d
@ -7,12 +7,12 @@ Painting::Painting(const Transform3d &obj_transform, const ModelVolumePtrs &volu
|
||||
auto model_transformation = obj_transform * mv->get_matrix();
|
||||
|
||||
indexed_triangle_set enforcers = mv->seam_facets
|
||||
.get_facets(*mv, EnforcerBlockerType::ENFORCER);
|
||||
.get_facets(*mv, TriangleStateType::ENFORCER);
|
||||
its_transform(enforcers, model_transformation);
|
||||
its_merge(this->enforcers, enforcers);
|
||||
|
||||
indexed_triangle_set blockers = mv->seam_facets
|
||||
.get_facets(*mv, EnforcerBlockerType::BLOCKER);
|
||||
.get_facets(*mv, TriangleStateType::BLOCKER);
|
||||
its_transform(blockers, model_transformation);
|
||||
its_merge(this->blockers, blockers);
|
||||
}
|
||||
|
@ -2021,7 +2021,7 @@ void ModelInstance::transform_polygon(Polygon* polygon) const
|
||||
polygon->scale(get_scaling_factor(X), get_scaling_factor(Y)); // scale around polygon origin
|
||||
}
|
||||
|
||||
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const
|
||||
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, TriangleStateType type) const
|
||||
{
|
||||
TriangleSelector selector(mv.mesh());
|
||||
// Reset of TriangleSelector is done inside TriangleSelector's constructor, so we don't need it to perform it again in deserialize().
|
||||
@ -2029,7 +2029,7 @@ indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, Enforce
|
||||
return selector.get_facets(type);
|
||||
}
|
||||
|
||||
indexed_triangle_set FacetsAnnotation::get_facets_strict(const ModelVolume& mv, EnforcerBlockerType type) const
|
||||
indexed_triangle_set FacetsAnnotation::get_facets_strict(const ModelVolume& mv, TriangleStateType type) const
|
||||
{
|
||||
TriangleSelector selector(mv.mesh());
|
||||
// Reset of TriangleSelector is done inside TriangleSelector's constructor, so we don't need it to perform it again in deserialize().
|
||||
@ -2037,7 +2037,7 @@ indexed_triangle_set FacetsAnnotation::get_facets_strict(const ModelVolume& mv,
|
||||
return selector.get_facets_strict(type);
|
||||
}
|
||||
|
||||
bool FacetsAnnotation::has_facets(const ModelVolume& mv, EnforcerBlockerType type) const
|
||||
bool FacetsAnnotation::has_facets(const ModelVolume& mv, TriangleStateType type) const
|
||||
{
|
||||
return TriangleSelector::has_facets(m_data, type);
|
||||
}
|
||||
|
@ -654,29 +654,6 @@ private:
|
||||
void update_min_max_z();
|
||||
};
|
||||
|
||||
enum class EnforcerBlockerType : int8_t {
|
||||
// Maximum is 3. The value is serialized in TriangleSelector into 2 bits.
|
||||
NONE = 0,
|
||||
ENFORCER = 1,
|
||||
BLOCKER = 2,
|
||||
// Maximum is 15. The value is serialized in TriangleSelector into 6 bits using a 2 bit prefix code.
|
||||
Extruder1 = ENFORCER,
|
||||
Extruder2 = BLOCKER,
|
||||
Extruder3,
|
||||
Extruder4,
|
||||
Extruder5,
|
||||
Extruder6,
|
||||
Extruder7,
|
||||
Extruder8,
|
||||
Extruder9,
|
||||
Extruder10,
|
||||
Extruder11,
|
||||
Extruder12,
|
||||
Extruder13,
|
||||
Extruder14,
|
||||
Extruder15,
|
||||
};
|
||||
|
||||
enum class ConversionType : int {
|
||||
CONV_TO_INCH,
|
||||
CONV_FROM_INCH,
|
||||
@ -691,9 +668,9 @@ public:
|
||||
void assign(FacetsAnnotation&& rhs) { if (! this->timestamp_matches(rhs)) { m_data = std::move(rhs.m_data); this->copy_timestamp(rhs); } }
|
||||
const TriangleSelector::TriangleSplittingData &get_data() const throw() { return m_data; }
|
||||
bool set(const TriangleSelector& selector);
|
||||
indexed_triangle_set get_facets(const ModelVolume& mv, EnforcerBlockerType type) const;
|
||||
indexed_triangle_set get_facets_strict(const ModelVolume& mv, EnforcerBlockerType type) const;
|
||||
bool has_facets(const ModelVolume& mv, EnforcerBlockerType type) const;
|
||||
indexed_triangle_set get_facets(const ModelVolume& mv, TriangleStateType type) const;
|
||||
indexed_triangle_set get_facets_strict(const ModelVolume& mv, TriangleStateType type) const;
|
||||
bool has_facets(const ModelVolume& mv, TriangleStateType type) const;
|
||||
bool empty() const { return m_data.triangles_to_split.empty(); }
|
||||
|
||||
// Following method clears the config and increases its timestamp, so the deleted
|
||||
@ -718,9 +695,9 @@ private:
|
||||
// by an existing ID copied from elsewhere.
|
||||
explicit FacetsAnnotation(int) : ObjectWithTimestamp(-1) {}
|
||||
// Copy constructor copies the ID.
|
||||
explicit FacetsAnnotation(const FacetsAnnotation &rhs) = default;
|
||||
FacetsAnnotation(const FacetsAnnotation &rhs) = default;
|
||||
// Move constructor copies the ID.
|
||||
explicit FacetsAnnotation(FacetsAnnotation &&rhs) = default;
|
||||
FacetsAnnotation(FacetsAnnotation &&rhs) = default;
|
||||
|
||||
// called by ModelVolume::assign_copy()
|
||||
FacetsAnnotation& operator=(const FacetsAnnotation &rhs) = default;
|
||||
@ -729,10 +706,7 @@ private:
|
||||
friend class cereal::access;
|
||||
friend class UndoRedo::StackImpl;
|
||||
|
||||
template<class Archive> void serialize(Archive &ar)
|
||||
{
|
||||
ar(cereal::base_class<ObjectWithTimestamp>(this), m_data);
|
||||
}
|
||||
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ObjectWithTimestamp>(this), m_data); }
|
||||
|
||||
TriangleSelector::TriangleSplittingData m_data;
|
||||
|
||||
|
@ -894,7 +894,7 @@ static inline std::vector<std::vector<ExPolygons>> mm_segmentation_top_and_botto
|
||||
if (mv->is_model_part()) {
|
||||
const Transform3d volume_trafo = object_trafo * mv->get_matrix();
|
||||
for (size_t extruder_idx = 0; extruder_idx < num_extruders; ++ extruder_idx) {
|
||||
const indexed_triangle_set painted = mv->mm_segmentation_facets.get_facets_strict(*mv, EnforcerBlockerType(extruder_idx));
|
||||
const indexed_triangle_set painted = mv->mm_segmentation_facets.get_facets_strict(*mv, TriangleStateType(extruder_idx));
|
||||
#ifdef MM_SEGMENTATION_DEBUG_TOP_BOTTOM
|
||||
{
|
||||
static int iRun = 0;
|
||||
@ -1298,7 +1298,7 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(1, num_extruders + 1), [&mv, &print_object, &layers, &edge_grids, &painted_lines, &painted_lines_mutex, &input_expolygons, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t extruder_idx = range.begin(); extruder_idx < range.end(); ++extruder_idx) {
|
||||
throw_on_cancel_callback();
|
||||
const indexed_triangle_set custom_facets = mv->mm_segmentation_facets.get_facets(*mv, EnforcerBlockerType(extruder_idx));
|
||||
const indexed_triangle_set custom_facets = mv->mm_segmentation_facets.get_facets(*mv, TriangleStateType(extruder_idx));
|
||||
if (!mv->is_model_part() || custom_facets.indices.empty())
|
||||
continue;
|
||||
|
||||
|
@ -760,7 +760,7 @@ std::string Print::validate(std::vector<std::string>* warnings) const
|
||||
if (! object->has_support() && warnings) {
|
||||
for (const ModelVolume* mv : object->model_object()->volumes) {
|
||||
bool has_enforcers = mv->is_support_enforcer() ||
|
||||
(mv->is_model_part() && mv->supported_facets.has_facets(*mv, EnforcerBlockerType::ENFORCER));
|
||||
(mv->is_model_part() && mv->supported_facets.has_facets(*mv, TriangleStateType::ENFORCER));
|
||||
if (has_enforcers) {
|
||||
warnings->emplace_back("_SUPPORTS_OFF");
|
||||
break;
|
||||
|
@ -353,7 +353,7 @@ public:
|
||||
std::vector<Polygons> slice_support_enforcers() const { return this->slice_support_volumes(ModelVolumeType::SUPPORT_ENFORCER); }
|
||||
|
||||
// Helpers to project custom facets on slices
|
||||
void project_and_append_custom_facets(bool seam, EnforcerBlockerType type, std::vector<Polygons>& expolys) const;
|
||||
void project_and_append_custom_facets(bool seam, TriangleStateType type, std::vector<Polygons>& expolys) const;
|
||||
|
||||
private:
|
||||
// to be called from Print only.
|
||||
|
@ -3150,7 +3150,7 @@ static void project_triangles_to_slabs(SpanOfConstPtrs<Layer> layers, const inde
|
||||
}
|
||||
|
||||
void PrintObject::project_and_append_custom_facets(
|
||||
bool seam, EnforcerBlockerType type, std::vector<Polygons>& out) const
|
||||
bool seam, TriangleStateType type, std::vector<Polygons>& out) const
|
||||
{
|
||||
for (const ModelVolume* mv : this->model_object()->volumes)
|
||||
if (mv->is_model_part()) {
|
||||
|
@ -1106,8 +1106,8 @@ struct SupportAnnotations
|
||||
buildplate_covered(buildplate_covered)
|
||||
{
|
||||
// Append custom supports.
|
||||
object.project_and_append_custom_facets(false, EnforcerBlockerType::ENFORCER, enforcers_layers);
|
||||
object.project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers_layers);
|
||||
object.project_and_append_custom_facets(false, TriangleStateType::ENFORCER, enforcers_layers);
|
||||
object.project_and_append_custom_facets(false, TriangleStateType::BLOCKER, blockers_layers);
|
||||
}
|
||||
|
||||
std::vector<Polygons> enforcers_layers;
|
||||
|
@ -207,8 +207,8 @@ static std::vector<std::pair<TreeSupportSettings, std::vector<size_t>>> group_me
|
||||
const int support_enforce_layers = config.support_material_enforce_layers.value;
|
||||
std::vector<Polygons> enforcers_layers{ print_object.slice_support_enforcers() };
|
||||
std::vector<Polygons> blockers_layers{ print_object.slice_support_blockers() };
|
||||
print_object.project_and_append_custom_facets(false, EnforcerBlockerType::ENFORCER, enforcers_layers);
|
||||
print_object.project_and_append_custom_facets(false, EnforcerBlockerType::BLOCKER, blockers_layers);
|
||||
print_object.project_and_append_custom_facets(false, TriangleStateType::ENFORCER, enforcers_layers);
|
||||
print_object.project_and_append_custom_facets(false, TriangleStateType::BLOCKER, blockers_layers);
|
||||
const int support_threshold = config.support_material_threshold.value;
|
||||
const bool support_threshold_auto = support_threshold == 0;
|
||||
// +1 makes the threshold inclusive
|
||||
|
@ -234,7 +234,7 @@ int TriangleSelector::select_unsplit_triangle(const Vec3f &hit, int facet_idx) c
|
||||
return this->select_unsplit_triangle(hit, facet_idx, neighbors);
|
||||
}
|
||||
|
||||
void TriangleSelector::select_patch(int facet_start, std::unique_ptr<Cursor> &&cursor, EnforcerBlockerType new_state, const Transform3d& trafo_no_translate, bool triangle_splitting, float highlight_by_angle_deg)
|
||||
void TriangleSelector::select_patch(int facet_start, std::unique_ptr<Cursor> &&cursor, TriangleStateType new_state, const Transform3d& trafo_no_translate, bool triangle_splitting, float highlight_by_angle_deg)
|
||||
{
|
||||
assert(facet_start < m_orig_size_indices);
|
||||
|
||||
@ -455,7 +455,7 @@ void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_
|
||||
return;
|
||||
|
||||
assert(!m_triangles[start_facet_idx].is_split());
|
||||
EnforcerBlockerType start_facet_state = m_triangles[start_facet_idx].get_state();
|
||||
TriangleStateType start_facet_state = m_triangles[start_facet_idx].get_state();
|
||||
this->seed_fill_unselect_all_triangles();
|
||||
|
||||
if (!propagate) {
|
||||
@ -511,8 +511,7 @@ void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_
|
||||
// This is done by an actual recursive call. Returns false if the triangle is
|
||||
// outside the cursor.
|
||||
// Called by select_patch() and by itself.
|
||||
bool TriangleSelector::select_triangle(int facet_idx, EnforcerBlockerType type, bool triangle_splitting)
|
||||
{
|
||||
bool TriangleSelector::select_triangle(int facet_idx, TriangleStateType type, bool triangle_splitting) {
|
||||
assert(facet_idx < int(m_triangles.size()));
|
||||
|
||||
if (! m_triangles[facet_idx].valid())
|
||||
@ -861,8 +860,7 @@ Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec
|
||||
return out;
|
||||
}
|
||||
|
||||
bool TriangleSelector::select_triangle_recursive(int facet_idx, const Vec3i &neighbors, EnforcerBlockerType type, bool triangle_splitting)
|
||||
{
|
||||
bool TriangleSelector::select_triangle_recursive(int facet_idx, const Vec3i &neighbors, TriangleStateType type, bool triangle_splitting) {
|
||||
assert(facet_idx < int(m_triangles.size()));
|
||||
|
||||
Triangle* tr = &m_triangles[facet_idx];
|
||||
@ -914,8 +912,7 @@ bool TriangleSelector::select_triangle_recursive(int facet_idx, const Vec3i &nei
|
||||
return true;
|
||||
}
|
||||
|
||||
void TriangleSelector::set_facet(int facet_idx, EnforcerBlockerType state)
|
||||
{
|
||||
void TriangleSelector::set_facet(int facet_idx, TriangleStateType state) {
|
||||
assert(facet_idx < m_orig_size_indices);
|
||||
undivide_triangle(facet_idx);
|
||||
assert(! m_triangles[facet_idx].is_split());
|
||||
@ -934,7 +931,7 @@ void TriangleSelector::split_triangle(int facet_idx, const Vec3i &neighbors)
|
||||
Triangle* tr = &m_triangles[facet_idx];
|
||||
assert(this->verify_triangle_neighbors(*tr, neighbors));
|
||||
|
||||
EnforcerBlockerType old_type = tr->get_state();
|
||||
TriangleStateType old_type = tr->get_state();
|
||||
|
||||
// If we got here, we are about to actually split the triangle.
|
||||
const double limit_squared = m_edge_limit_sqr;
|
||||
@ -1117,7 +1114,7 @@ void TriangleSelector::remove_useless_children(int facet_idx)
|
||||
|
||||
|
||||
// Return if a child is not leaf or two children differ in type.
|
||||
EnforcerBlockerType first_child_type = EnforcerBlockerType::NONE;
|
||||
TriangleStateType first_child_type = TriangleStateType::NONE;
|
||||
for (int child_idx=0; child_idx<=tr.number_of_split_sides(); ++child_idx) {
|
||||
if (m_triangles[tr.children[child_idx]].is_split())
|
||||
return;
|
||||
@ -1217,8 +1214,7 @@ void TriangleSelector::set_edge_limit(float edge_limit)
|
||||
m_edge_limit_sqr = std::pow(edge_limit, 2.f);
|
||||
}
|
||||
|
||||
int TriangleSelector::push_triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType state)
|
||||
{
|
||||
int TriangleSelector::push_triangle(int a, int b, int c, int source_triangle, const TriangleStateType state) {
|
||||
for (int i : {a, b, c}) {
|
||||
assert(i >= 0 && i < int(m_vertices.size()));
|
||||
++m_vertices[i].ref_cnt;
|
||||
@ -1251,8 +1247,7 @@ int TriangleSelector::push_triangle(int a, int b, int c, int source_triangle, co
|
||||
// Split a triangle based on Triangle::number_of_split_sides() and Triangle::special_side()
|
||||
// by allocating child triangles and midpoint vertices.
|
||||
// Midpoint vertices are possibly reused by traversing children of neighbor triangles.
|
||||
void TriangleSelector::perform_split(int facet_idx, const Vec3i &neighbors, EnforcerBlockerType old_state)
|
||||
{
|
||||
void TriangleSelector::perform_split(int facet_idx, const Vec3i &neighbors, TriangleStateType old_state) {
|
||||
// Reserve space for the new triangles upfront, so that the reference to this triangle will not change.
|
||||
{
|
||||
size_t num_triangles_new = m_triangles.size() + m_triangles[facet_idx].number_of_split_sides() + 1;
|
||||
@ -1318,16 +1313,14 @@ void TriangleSelector::perform_split(int facet_idx, const Vec3i &neighbors, Enfo
|
||||
#endif // NDEBUG
|
||||
}
|
||||
|
||||
bool TriangleSelector::has_facets(EnforcerBlockerType state) const
|
||||
{
|
||||
bool TriangleSelector::has_facets(TriangleStateType state) const {
|
||||
for (const Triangle& tr : m_triangles)
|
||||
if (tr.valid() && ! tr.is_split() && tr.get_state() == state)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int TriangleSelector::num_facets(EnforcerBlockerType state) const
|
||||
{
|
||||
int TriangleSelector::num_facets(TriangleStateType state) const {
|
||||
int cnt = 0;
|
||||
for (const Triangle& tr : m_triangles)
|
||||
if (tr.valid() && ! tr.is_split() && tr.get_state() == state)
|
||||
@ -1335,8 +1328,7 @@ int TriangleSelector::num_facets(EnforcerBlockerType state) const
|
||||
return cnt;
|
||||
}
|
||||
|
||||
indexed_triangle_set TriangleSelector::get_facets(EnforcerBlockerType state) const
|
||||
{
|
||||
indexed_triangle_set TriangleSelector::get_facets(TriangleStateType state) const {
|
||||
indexed_triangle_set out;
|
||||
std::vector<int> vertex_map(m_vertices.size(), -1);
|
||||
for (const Triangle& tr : m_triangles) {
|
||||
@ -1356,8 +1348,7 @@ indexed_triangle_set TriangleSelector::get_facets(EnforcerBlockerType state) con
|
||||
return out;
|
||||
}
|
||||
|
||||
indexed_triangle_set TriangleSelector::get_facets_strict(EnforcerBlockerType state) const
|
||||
{
|
||||
indexed_triangle_set TriangleSelector::get_facets_strict(TriangleStateType state) const {
|
||||
indexed_triangle_set out;
|
||||
|
||||
size_t num_vertices = 0;
|
||||
@ -1385,7 +1376,7 @@ indexed_triangle_set TriangleSelector::get_facets_strict(EnforcerBlockerType sta
|
||||
void TriangleSelector::get_facets_strict_recursive(
|
||||
const Triangle &tr,
|
||||
const Vec3i &neighbors,
|
||||
EnforcerBlockerType state,
|
||||
TriangleStateType state,
|
||||
std::vector<stl_triangle_vertex_indices> &out_triangles) const
|
||||
{
|
||||
if (tr.is_split()) {
|
||||
@ -1529,8 +1520,8 @@ void TriangleSelector::get_seed_fill_contour_recursive(const int facet_idx, cons
|
||||
TriangleSelector::TriangleSplittingData TriangleSelector::serialize() const {
|
||||
// Each original triangle of the mesh is assigned a number encoding its state
|
||||
// or how it is split. Each triangle is encoded by 4 bits (xxyy) or 8 bits (zzzzxxyy):
|
||||
// leaf triangle: xx = EnforcerBlockerType (Only values 0, 1, and 2. Value 3 is used as an indicator for additional 4 bits.), yy = 0
|
||||
// leaf triangle: xx = 0b11, yy = 0b00, zzzz = EnforcerBlockerType (subtracted by 3)
|
||||
// leaf triangle: xx = TriangleStateType (Only values 0, 1, and 2. Value 3 is used as an indicator for additional 4 bits.), yy = 0
|
||||
// leaf triangle: xx = 0b11, yy = 0b00, zzzz = TriangleStateType (subtracted by 3)
|
||||
// non-leaf: xx = special side, yy = number of split sides
|
||||
// These are bitwise appended and formed into one 64-bit integer.
|
||||
|
||||
@ -1590,7 +1581,7 @@ TriangleSelector::TriangleSplittingData TriangleSelector::serialize() const {
|
||||
|
||||
out.data.triangles_to_split.reserve(m_orig_size_indices);
|
||||
for (int i=0; i<m_orig_size_indices; ++i)
|
||||
if (const Triangle& tr = m_triangles[i]; tr.is_split() || tr.get_state() != EnforcerBlockerType::NONE) {
|
||||
if (const Triangle& tr = m_triangles[i]; tr.is_split() || tr.get_state() != TriangleStateType::NONE) {
|
||||
// Store index of the first bit assigned to ith triangle.
|
||||
out.data.triangles_to_split.emplace_back(i, int(out.data.bitstream.size()));
|
||||
// out the triangle bits.
|
||||
@ -1643,7 +1634,7 @@ void TriangleSelector::deserialize(const TriangleSplittingData &data, bool needs
|
||||
int num_of_children = num_of_split_sides == 0 ? 0 : num_of_split_sides + 1;
|
||||
bool is_split = num_of_children != 0;
|
||||
// Only valid if not is_split. Value of the second nibble was subtracted by 3, so it is added back.
|
||||
auto state = is_split ? EnforcerBlockerType::NONE : EnforcerBlockerType((code & 0b1100) == 0b1100 ? next_nibble() + 3 : code >> 2);
|
||||
auto state = is_split ? TriangleStateType::NONE : TriangleStateType((code & 0b1100) == 0b1100 ? next_nibble() + 3 : code >> 2);
|
||||
// Only valid if is_split.
|
||||
int special_side = code >> 2;
|
||||
|
||||
@ -1655,7 +1646,7 @@ void TriangleSelector::deserialize(const TriangleSplittingData &data, bool needs
|
||||
Vec3i neighbors = m_neighbors[triangle_id];
|
||||
parents.push_back({triangle_id, neighbors, 0, num_of_children});
|
||||
m_triangles[triangle_id].set_division(num_of_split_sides, special_side);
|
||||
perform_split(triangle_id, neighbors, EnforcerBlockerType::NONE);
|
||||
perform_split(triangle_id, neighbors, TriangleStateType::NONE);
|
||||
continue;
|
||||
} else {
|
||||
// root is not split. just set the state and that's it.
|
||||
@ -1675,7 +1666,7 @@ void TriangleSelector::deserialize(const TriangleSplittingData &data, bool needs
|
||||
Vec3i neighbors = this->child_neighbors(tr, last.neighbors, child_idx);
|
||||
int this_idx = tr.children[child_idx];
|
||||
m_triangles[this_idx].set_division(num_of_split_sides, special_side);
|
||||
perform_split(this_idx, neighbors, EnforcerBlockerType::NONE);
|
||||
perform_split(this_idx, neighbors, TriangleStateType::NONE);
|
||||
parents.push_back({this_idx, neighbors, 0, num_of_children});
|
||||
} else {
|
||||
// this triangle belongs to last split one
|
||||
@ -1704,7 +1695,7 @@ void TriangleSelector::deserialize(const TriangleSplittingData &data, bool needs
|
||||
}
|
||||
|
||||
// Lightweight variant of deserialization, which only tests whether a face of test_state exists.
|
||||
bool TriangleSelector::has_facets(const TriangleSplittingData &data, const EnforcerBlockerType test_state) {
|
||||
bool TriangleSelector::has_facets(const TriangleSplittingData &data, const TriangleStateType test_state) {
|
||||
// Depth-first queue of a number of unvisited children.
|
||||
// Kept outside of the loop to avoid re-allocating inside the loop.
|
||||
std::vector<int> parents_children;
|
||||
@ -1761,8 +1752,7 @@ void TriangleSelector::seed_fill_unselect_all_triangles()
|
||||
triangle.unselect_by_seed_fill();
|
||||
}
|
||||
|
||||
void TriangleSelector::seed_fill_apply_on_triangles(EnforcerBlockerType new_state)
|
||||
{
|
||||
void TriangleSelector::seed_fill_apply_on_triangles(TriangleStateType new_state) {
|
||||
for (Triangle &triangle : m_triangles)
|
||||
if (!triangle.is_split() && triangle.is_selected_by_seed_fill())
|
||||
triangle.set_state(new_state);
|
||||
|
@ -14,8 +14,29 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class EnforcerBlockerType : int8_t;
|
||||
|
||||
enum class TriangleStateType : int8_t {
|
||||
// Maximum is 3. The value is serialized in TriangleSelector into 2 bits.
|
||||
NONE = 0,
|
||||
ENFORCER = 1,
|
||||
BLOCKER = 2,
|
||||
// Maximum is 15. The value is serialized in TriangleSelector into 6 bits using a 2 bit prefix code.
|
||||
Extruder1 = ENFORCER,
|
||||
Extruder2 = BLOCKER,
|
||||
Extruder3,
|
||||
Extruder4,
|
||||
Extruder5,
|
||||
Extruder6,
|
||||
Extruder7,
|
||||
Extruder8,
|
||||
Extruder9,
|
||||
Extruder10,
|
||||
Extruder11,
|
||||
Extruder12,
|
||||
Extruder13,
|
||||
Extruder14,
|
||||
Extruder15,
|
||||
Count
|
||||
};
|
||||
|
||||
// Following class holds information about selected triangles. It also has power
|
||||
// to recursively subdivide the triangles and make the selection finer.
|
||||
@ -206,7 +227,7 @@ public:
|
||||
// Vector of triangles and its indexes to the bitstream.
|
||||
std::vector<TriangleBitStreamMapping> triangles_to_split;
|
||||
// Bit stream containing splitting information.
|
||||
std::vector<bool> bitstream;
|
||||
std::vector<bool> bitstream;
|
||||
|
||||
TriangleSplittingData() = default;
|
||||
|
||||
@ -236,7 +257,7 @@ public:
|
||||
// Select all triangles fully inside the circle, subdivide where needed.
|
||||
void select_patch(int facet_start, // facet of the original mesh (unsplit) that the hit point belongs to
|
||||
std::unique_ptr<Cursor> &&cursor, // Cursor containing information about the point where to start, camera position (mesh coords), matrix to get from mesh to world, and its shape and type.
|
||||
EnforcerBlockerType new_state, // enforcer or blocker?
|
||||
TriangleStateType new_state, // enforcer or blocker?
|
||||
const Transform3d &trafo_no_translate, // matrix to get from mesh to world without translation
|
||||
bool triangle_splitting, // If triangles will be split base on the cursor or not
|
||||
float highlight_by_angle_deg = 0.f); // The maximal angle of overhang. If it is set to a non-zero value, it is possible to paint only the triangles of overhang defined by this angle in degrees.
|
||||
@ -255,18 +276,18 @@ public:
|
||||
bool propagate, // if bucket fill is propagated to neighbor faces or if it fills the only facet of the modified mesh that the hit point belongs to.
|
||||
bool force_reselection = false); // force reselection of the triangle mesh even in cases that mouse is pointing on the selected triangle
|
||||
|
||||
bool has_facets(EnforcerBlockerType state) const;
|
||||
static bool has_facets(const TriangleSplittingData &data, EnforcerBlockerType test_state);
|
||||
int num_facets(EnforcerBlockerType state) const;
|
||||
bool has_facets(TriangleStateType state) const;
|
||||
static bool has_facets(const TriangleSplittingData &data, TriangleStateType test_state);
|
||||
int num_facets(TriangleStateType state) const;
|
||||
// Get facets at a given state. Don't triangulate T-joints.
|
||||
indexed_triangle_set get_facets(EnforcerBlockerType state) const;
|
||||
indexed_triangle_set get_facets(TriangleStateType state) const;
|
||||
// Get facets at a given state. Triangulate T-joints.
|
||||
indexed_triangle_set get_facets_strict(EnforcerBlockerType state) const;
|
||||
indexed_triangle_set get_facets_strict(TriangleStateType state) const;
|
||||
// Get edges around the selected area by seed fill.
|
||||
std::vector<Vec2i> get_seed_fill_contour() const;
|
||||
|
||||
// Set facet of the mesh to a given state. Only works for original triangles.
|
||||
void set_facet(int facet_idx, EnforcerBlockerType state);
|
||||
void set_facet(int facet_idx, TriangleStateType state);
|
||||
|
||||
// Clear everything and make the tree empty.
|
||||
void reset();
|
||||
@ -284,9 +305,9 @@ public:
|
||||
// For all triangles, remove the flag indicating that the triangle was selected by seed fill.
|
||||
void seed_fill_unselect_all_triangles();
|
||||
|
||||
// For all triangles selected by seed fill, set new EnforcerBlockerType and remove flag indicating that triangle was selected by seed fill.
|
||||
// For all triangles selected by seed fill, set new TriangleStateType and remove flag indicating that triangle was selected by seed fill.
|
||||
// The operation may merge split triangles if they are being assigned the same color.
|
||||
void seed_fill_apply_on_triangles(EnforcerBlockerType new_state);
|
||||
void seed_fill_apply_on_triangles(TriangleStateType new_state);
|
||||
|
||||
protected:
|
||||
// Triangle and info about how it's split.
|
||||
@ -294,7 +315,7 @@ protected:
|
||||
public:
|
||||
// Use TriangleSelector::push_triangle to create a new triangle.
|
||||
// It increments/decrements reference counter on vertices.
|
||||
Triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType init_state)
|
||||
Triangle(int a, int b, int c, int source_triangle, const TriangleStateType init_state)
|
||||
: verts_idxs{a, b, c},
|
||||
source_triangle{source_triangle},
|
||||
state{init_state}
|
||||
@ -316,8 +337,8 @@ protected:
|
||||
void set_division(int sides_to_split, int special_side_idx);
|
||||
|
||||
// Get/set current state.
|
||||
void set_state(EnforcerBlockerType type) { assert(! is_split()); state = type; }
|
||||
EnforcerBlockerType get_state() const { assert(! is_split()); return state; }
|
||||
void set_state(TriangleStateType type) { assert(! is_split()); state = type; }
|
||||
TriangleStateType get_state() const { assert(! is_split()); return state; }
|
||||
|
||||
// Set if the triangle has been selected or unselected by seed fill.
|
||||
void select_by_seed_fill() { assert(! is_split()); m_selected_by_seed_fill = true; }
|
||||
@ -341,7 +362,7 @@ protected:
|
||||
// or index of a vertex shared by the two split edges (for number_of_splits == 2).
|
||||
// For number_of_splits == 3, special_side_idx is always zero.
|
||||
char special_side_idx { 0 };
|
||||
EnforcerBlockerType state;
|
||||
TriangleStateType state;
|
||||
bool m_selected_by_seed_fill : 1;
|
||||
// Is this triangle valid or marked to be removed?
|
||||
bool m_valid : 1;
|
||||
@ -379,14 +400,14 @@ protected:
|
||||
|
||||
// Private functions:
|
||||
private:
|
||||
bool select_triangle(int facet_idx, EnforcerBlockerType type, bool triangle_splitting);
|
||||
bool select_triangle_recursive(int facet_idx, const Vec3i &neighbors, EnforcerBlockerType type, bool triangle_splitting);
|
||||
bool select_triangle(int facet_idx, TriangleStateType type, bool triangle_splitting);
|
||||
bool select_triangle_recursive(int facet_idx, const Vec3i &neighbors, TriangleStateType type, bool triangle_splitting);
|
||||
void undivide_triangle(int facet_idx);
|
||||
void split_triangle(int facet_idx, const Vec3i &neighbors);
|
||||
void remove_useless_children(int facet_idx); // No hidden meaning. Triangles are meant.
|
||||
bool is_facet_clipped(int facet_idx, const ClippingPlane &clp) const;
|
||||
int push_triangle(int a, int b, int c, int source_triangle, EnforcerBlockerType state = EnforcerBlockerType{0});
|
||||
void perform_split(int facet_idx, const Vec3i &neighbors, EnforcerBlockerType old_state);
|
||||
int push_triangle(int a, int b, int c, int source_triangle, TriangleStateType state = TriangleStateType::NONE);
|
||||
void perform_split(int facet_idx, const Vec3i &neighbors, TriangleStateType old_state);
|
||||
Vec3i child_neighbors(const Triangle &tr, const Vec3i &neighbors, int child_idx) const;
|
||||
Vec3i child_neighbors_propagated(const Triangle &tr, const Vec3i &neighbors_propagated, int child_idx, const Vec3i &child_neighbors) const;
|
||||
// Return child of itriangle at a CCW oriented side (vertexi, vertexj), either first or 2nd part.
|
||||
@ -415,7 +436,7 @@ private:
|
||||
void get_facets_strict_recursive(
|
||||
const Triangle &tr,
|
||||
const Vec3i &neighbors,
|
||||
EnforcerBlockerType state,
|
||||
TriangleStateType state,
|
||||
std::vector<stl_triangle_vertex_indices> &out_triangles) const;
|
||||
void get_facets_split_by_tjoints(const Vec3i &vertices, const Vec3i &neighbors, std::vector<stl_triangle_vertex_indices> &out_triangles) const;
|
||||
|
||||
|
@ -29,7 +29,7 @@ void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, const Vec3f &orig
|
||||
if ((point - pos).norm() < radius && face_normal.dot(dir) < 0) {
|
||||
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||
pos, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||
selector.select_patch(hit.id, std::move(cursor), EnforcerBlockerType::ENFORCER, trafo_no_translate,
|
||||
selector.select_patch(hit.id, std::move(cursor), TriangleStateType::ENFORCER, trafo_no_translate,
|
||||
true, eps_angle);
|
||||
break;
|
||||
}
|
||||
@ -42,7 +42,7 @@ void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, const Vec3f &orig
|
||||
if (dist < radius) {
|
||||
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||
point, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||
selector.select_patch(hit_idx_out, std::move(cursor), EnforcerBlockerType::ENFORCER,
|
||||
selector.select_patch(hit_idx_out, std::move(cursor), TriangleStateType::ENFORCER,
|
||||
trafo_no_translate,
|
||||
true, eps_angle);
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
|
||||
const indexed_triangle_set &its = mv->mesh().its;
|
||||
for (const stl_triangle_vertex_indices &face : its.indices) {
|
||||
if (its_face_normal(its, face).dot(down) > dot_limit) {
|
||||
m_triangle_selectors[mesh_id]->set_facet(idx, block ? EnforcerBlockerType::BLOCKER : EnforcerBlockerType::ENFORCER);
|
||||
m_triangle_selectors[mesh_id]->set_facet(idx, block ? TriangleStateType::BLOCKER : TriangleStateType::ENFORCER);
|
||||
m_triangle_selectors.back()->request_update_render_data();
|
||||
}
|
||||
++ idx;
|
||||
|
@ -110,8 +110,8 @@ protected:
|
||||
ColorRGBA get_cursor_sphere_left_button_color() const override;
|
||||
ColorRGBA get_cursor_sphere_right_button_color() const override;
|
||||
|
||||
EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx + 1); }
|
||||
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx + 1); }
|
||||
TriangleStateType get_left_button_state_type() const override { return TriangleStateType(m_first_selected_extruder_idx + 1); }
|
||||
TriangleStateType get_right_button_state_type() const override { return TriangleStateType(m_second_selected_extruder_idx + 1); }
|
||||
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
std::string on_get_name() const override;
|
||||
|
@ -503,7 +503,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
if (m_triangle_selectors.empty())
|
||||
return false;
|
||||
|
||||
EnforcerBlockerType new_state = EnforcerBlockerType::NONE;
|
||||
TriangleStateType new_state = TriangleStateType::NONE;
|
||||
if (! shift_down) {
|
||||
if (action == SLAGizmoEventType::Dragging)
|
||||
new_state = m_button_down == Button::Left ? this->get_left_button_state_type() : this->get_right_button_state_type();
|
||||
@ -937,16 +937,16 @@ void TriangleSelectorGUI::update_render_data()
|
||||
static const float offset = 0.001f;
|
||||
|
||||
for (const Triangle &tr : m_triangles) {
|
||||
if (!tr.valid() || tr.is_split() || (tr.get_state() == EnforcerBlockerType::NONE && !tr.is_selected_by_seed_fill()))
|
||||
if (!tr.valid() || tr.is_split() || (tr.get_state() == TriangleStateType::NONE && !tr.is_selected_by_seed_fill()))
|
||||
continue;
|
||||
|
||||
int tr_state = int(tr.get_state());
|
||||
GLModel::Geometry &iva = tr.is_selected_by_seed_fill() ? iva_seed_fills_data[tr_state] :
|
||||
tr.get_state() == EnforcerBlockerType::ENFORCER ? iva_enforcers_data :
|
||||
iva_blockers_data;
|
||||
int &cnt = tr.is_selected_by_seed_fill() ? seed_fill_cnt[tr_state] :
|
||||
tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt :
|
||||
blc_cnt;
|
||||
GLModel::Geometry &iva = tr.is_selected_by_seed_fill() ? iva_seed_fills_data[tr_state] :
|
||||
tr.get_state() == TriangleStateType::ENFORCER ? iva_enforcers_data :
|
||||
iva_blockers_data;
|
||||
int &cnt = tr.is_selected_by_seed_fill() ? seed_fill_cnt[tr_state] :
|
||||
tr.get_state() == TriangleStateType::ENFORCER ? enf_cnt :
|
||||
blc_cnt;
|
||||
const Vec3f &v0 = m_vertices[tr.verts_idxs[0]].v;
|
||||
const Vec3f &v1 = m_vertices[tr.verts_idxs[1]].v;
|
||||
const Vec3f &v2 = m_vertices[tr.verts_idxs[2]].v;
|
||||
|
@ -120,8 +120,8 @@ protected:
|
||||
virtual ColorRGBA get_cursor_sphere_left_button_color() const { return { 0.0f, 0.0f, 1.0f, 0.25f }; }
|
||||
virtual ColorRGBA get_cursor_sphere_right_button_color() const { return { 1.0f, 0.0f, 0.0f, 0.25f }; }
|
||||
|
||||
virtual EnforcerBlockerType get_left_button_state_type() const { return EnforcerBlockerType::ENFORCER; }
|
||||
virtual EnforcerBlockerType get_right_button_state_type() const { return EnforcerBlockerType::BLOCKER; }
|
||||
virtual TriangleStateType get_left_button_state_type() const { return TriangleStateType::ENFORCER; }
|
||||
virtual TriangleStateType get_right_button_state_type() const { return TriangleStateType::BLOCKER; }
|
||||
|
||||
float m_cursor_radius = 2.f;
|
||||
static constexpr float CursorRadiusMin = 0.4f; // cannot be zero
|
||||
|
Loading…
x
Reference in New Issue
Block a user