TriangleSelector optimizations:

1) When splitting a triangle, vertices are now properly shared with
   the neighbor triangles, if these are already split.
   Please note that the splitting may not be regular if the splitting
   thershold is changed between splitting calls. Still the new code
   shares the vertices accross shared edges properly.
2) Triangles resp. vertices are newly reused after deleted using
   linked lists of released triangles resp. vertices.
   This mechanism replaces the old mechanism of reusing already split
   triangles.
This commit is contained in:
Vojtech Bubnik 2021-06-15 14:43:37 +02:00
parent 0b5ea8f429
commit 154e552006
2 changed files with 450 additions and 157 deletions

View file

@ -12,7 +12,6 @@ namespace Slic3r {
enum class EnforcerBlockerType : int8_t;
// Following class holds information about selected triangles. It also has power
// to recursively subdivide the triangles and make the selection finer.
class TriangleSelector {
@ -84,7 +83,6 @@ protected:
// Initialize bit fields. Default member initializers are not supported by C++17.
m_selected_by_seed_fill = false;
m_valid = true;
old_number_of_splits = 0;
}
// Indices into m_vertices.
std::array<int, 3> verts_idxs;
@ -96,7 +94,7 @@ protected:
std::array<int, 4> children;
// Set the division type.
void set_division(int sides_to_split, int special_side_idx = -1);
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; }
@ -114,8 +112,6 @@ protected:
bool is_split() const throw() { return number_of_split_sides() != 0; }
int number_of_split_sides() const throw() { return number_of_splits; }
int special_side() const throw() { assert(is_split()); return special_side_idx; }
bool was_split_before() const throw() { return old_number_of_splits != 0; }
void forget_history() { old_number_of_splits = 0; }
private:
friend TriangleSelector;
@ -130,12 +126,6 @@ protected:
bool m_selected_by_seed_fill : 1;
// Is this triangle valid or marked to be removed?
bool m_valid : 1;
// How many children were spawned during last split?
// Is not reset on remerging the triangle.
int old_number_of_splits : 3;
// there are still 3 bits available at the last byte :-)
};
struct Vertex {
@ -185,16 +175,37 @@ protected:
// Private functions:
private:
bool select_triangle(int facet_idx, EnforcerBlockerType type, bool recursive_call = false, bool triangle_splitting = true);
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);
int vertices_inside(int facet_idx) const;
bool faces_camera(int facet) const;
void undivide_triangle(int facet_idx);
void split_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_pointer_in_triangle(int facet_idx) const;
bool is_edge_inside_cursor(int facet_idx) const;
void push_triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType state = EnforcerBlockerType{0});
void perform_split(int facet_idx, EnforcerBlockerType old_state);
int push_triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType state = EnforcerBlockerType{0});
void perform_split(int facet_idx, const Vec3i &neighbors, EnforcerBlockerType old_state);
Vec3i child_neighbors(const Triangle &tr, const Vec3i &neighbors, int child_idx) const;
// Return child of itriangle at a CCW oriented side (vertexi, vertexj), either first or 2nd part.
// If itriangle == -1 or if the side sharing (vertexi, vertexj) is not split, return -1.
enum class Partition {
First,
Second,
};
int neighbor_child(const Triangle& tr, int vertexi, int vertexj, Partition partition) const;
int neighbor_child(int itriangle, int vertexi, int vertexj, Partition partition) const;
int triangle_midpoint(const Triangle& tr, int vertexi, int vertexj) const;
int triangle_midpoint(int itriangle, int vertexi, int vertexj) const;
int triangle_midpoint_or_allocate(int itriangle, int vertexi, int vertexj);
#ifndef _NDEBUG
bool verify_triangle_neighbors(const Triangle& tr, const Vec3i& neighbors) const;
bool verify_triangle_midpoints(const Triangle& tr) const;
#endif // _NDEBUG
int m_free_triangles_head { -1 };
int m_free_vertices_head { -1 };
};