From 953d1417a0a751ffcb9fc5c93d9e42a203a0cda4 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 11 Jun 2020 13:09:34 +0200 Subject: [PATCH] TriangleSelector: draft of interface --- src/libslic3r/Model.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 66 ++++++++++++++++++ src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp | 71 ++++++++++++++++++++ 3 files changed, 138 insertions(+) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index e5930fb8a..be298ae4b 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -394,6 +394,7 @@ enum class ModelVolumeType : int { }; enum class FacetSupportType : int8_t { + // Maximum is 3. The value is serialized in TriangleSelector into 2 bits! NONE = 0, ENFORCER = 1, BLOCKER = 2 diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index cd4285724..00e236b64 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -805,6 +805,10 @@ void GLGizmoFdmSupports::on_set_state() activate_internal_undo_redo_stack(true); }); } + + TriangleSelector ts{TriangleMesh()}; + ts.test(); + } if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off // we are actually shutting down @@ -854,5 +858,67 @@ void GLGizmoFdmSupports::on_save(cereal::BinaryOutputArchive&) const +void TriangleSelector::test() +{ + DivisionNode node; + while (true) { + std::cout << "Zadej pocet stran a spec stranu: "; + int num; + int spec; + std::cin >> num >> spec; + node.set_division(num, spec); + std::cout << node.number_of_split_sides() << " " + << (node.number_of_split_sides()==1 ? node.side_to_split() : node.side_to_keep()) + << std::endl << std::endl; + } +} + + +void TriangleSelector::DivisionNode::set_division(int sides_to_split, int special_side_idx) +{ + assert(sides_to_split >=0 && sides_to_split <= 3); + assert(special_side_idx >=-1 && special_side_idx < 3); + + // If splitting one or two sides, second argument must be provided. + assert(sides_to_split != 1 || special_side_idx != -1); + assert(sides_to_split != 2 || special_side_idx != -1); + + division_type = sides_to_split | (special_side_idx != -1 ? (special_side_idx << 2) : 0 ); +} + + + +void TriangleSelector::DivisionNode::set_type(FacetSupportType type) +{ + // If this is not a leaf-node, this makes no sense and + // the bits are used for storing index of an edge. + assert(number_of_split_sides() == 0); + division_type = type | (type << 2); +} + + + +int TriangleSelector::DivisionNode::side_to_keep() const +{ + assert(number_of_split_sides() == 2); + return (division_type & 0b1100) >> 2; +} + + + +int TriangleSelector::DivisionNode::side_to_split() const +{ + assert(number_of_split_sides() == 1); + return (division_type & 0b1100) >> 2; +} + + + +FacetSupportType TriangleSelector::DivisionNode::get_type() const +{ + assert(number_of_split_sides() == 0); // this must be leaf + return (division_type & 0b1100) >> 2; +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index c4f5b153e..f815a8063 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -19,6 +19,77 @@ namespace GUI { enum class SLAGizmoEventType : unsigned char; class ClippingPlane; + +// Following class holds information about selected triangles. It also has power +// to recursively subdivide the triangles and make the selection finer. +class TriangleSelector { +public: + void test(); + explicit TriangleSelector(const TriangleMesh& mesh) {} + + // Select all triangles inside the circle, subdivide where needed. + void select_patch(const Vec3f& hit, // point where to start + int facet_idx, // facet that point belongs to + const Vec3f& dir, // direction of the ray + float radius_sqr, // squared radius of the cursor + bool enforcer); // enforcer or blocker? + + void unselect_all(); + + // Remove all unnecessary data (such as vertices that are not needed + // because the selection has been made larger. + void garbage_collect(); + +private: + // A struct to hold information about how a triangle was divided. + struct DivisionNode { + // Index of triangle this describes. + int triangle_idx; + + // Bitmask encoding which sides are split. + unsigned char division_type; + // bits 0 and 1 : 00 - no division + // 01 - one-edge split + // 10 - two-edge split + // 11 - three-edge split + // bits 2 and 3 : decimal 0, 1 or 2 identifying the special edge (one that + // splits in one-edge split or one that stays in two-edge split). + + // Pointers to children nodes (not all are always used). + std::array children; + + // Set the division type. + void set_division(int sides_to_split, int special_side_idx = -1); + + // Helpers that decode the division_type bitmask. + int number_of_split_sides() const { return division_type & 0b11; } + int side_to_keep() const; + int side_to_split() const; + }; + + // Triangle and pointer to how it's divided (nullptr = not divided). + // The ptr is nullptr for all new triangles, it is only valid for + // the original (undivided) triangles. + struct Triangle { + stl_triangle_vertex_indices verts_idxs; + DivisionNode* div_info; + }; + + // Lists of vertices and triangles, both original and new + std::vector m_vertices; + std::vector m_triangles; + + // Number of original vertices and triangles. + int m_orig_size_vertices; + int m_orig_size_indices; + + // Limits for stopping the recursion. + float m_max_edge_length; + int m_max_recursion_depth; +}; + + + class GLGizmoFdmSupports : public GLGizmoBase { private: