diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index e2e9ec72a..1975d6eba 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -1467,6 +1467,19 @@ void GLGizmoCut3D::on_render() m_c->selection_info()->set_use_shift(true); } + + ::glDisable(GL_DEPTH_TEST); + std::vector pts = m_c->object_clipper()->point_per_contour(); + if (! pts.empty()) { + const Vec3d dir = (m_plane_center-pts.front()).dot(m_cut_normal) * m_cut_normal; + for (const Vec3d& pt : pts) + render_model(m_sphere.model, ColorRGBA::GREEN(), wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(pt+dir)); + } + ::glEnable(GL_DEPTH_TEST); + + + + update_clipper(); init_picking_models(); @@ -1733,7 +1746,7 @@ void GLGizmoCut3D::flip_cut_plane() } -GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx_in, const Vec3d& center, const Vec3d& normal) +GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx_in, const Vec3d& center, const Vec3d& normal, const CommonGizmosDataObjects::ObjectClipper& oc) { m_model = Model(); m_model.add_object(*mo); @@ -1773,6 +1786,15 @@ GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transfor } } } + + // Now go through the contours and create a map from contours to parts. + if (std::vector pts = oc.point_per_contour();! pts.empty()) { + const Vec3d dir = (center-pts.front()).dot(normal) * normal; + for (Vec3d& pt : pts) + pt = pt+dir; + // pts are now in world coordinates. + } + m_valid = true; } @@ -1798,7 +1820,7 @@ void GLGizmoCut3D::process_contours() const int instance_idx = selection.get_instance_idx(); const int object_idx = selection.get_object_idx(); - m_part_selection = PartSelection(model_objects[object_idx], get_cut_matrix(selection), instance_idx, m_plane_center, m_cut_normal); + m_part_selection = PartSelection(model_objects[object_idx], get_cut_matrix(selection), instance_idx, m_plane_center, m_cut_normal, *m_c->object_clipper()); m_parent.toggle_model_objects_visibility(false); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 4108690a6..b765ce14b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -20,6 +20,8 @@ class Selection; enum class SLAGizmoEventType : unsigned char; +namespace CommonGizmosDataObjects { class ObjectClipper; } + class GLGizmoCut3D : public GLGizmoBase { enum GrabberID { @@ -140,7 +142,7 @@ class GLGizmoCut3D : public GLGizmoBase class PartSelection { public: PartSelection() = default; - PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx, const Vec3d& center, const Vec3d& normal); + PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx, const Vec3d& center, const Vec3d& normal, const CommonGizmosDataObjects::ObjectClipper& oc); struct Part { GLModel glmodel; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 549540610..3d7b77a50 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -370,21 +370,30 @@ void ObjectClipper::on_release() } -void ObjectClipper::render_cut() const +void ObjectClipper::render_cut(const std::vector* ignore_idxs) const { if (m_clp_ratio == 0.) return; const SelectionInfo* sel_info = get_pool()->selection_info(); const Geometry::Transformation inst_trafo = sel_info->model_object()->instances[sel_info->get_active_instance()]->get_transformation(); + + std::vector ignore_idxs_local = ignore_idxs ? *ignore_idxs : std::vector(); for (auto& clipper : m_clippers) { - Geometry::Transformation trafo = inst_trafo * clipper.second; - trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); - clipper.first->set_plane(*m_clp); - clipper.first->set_transformation(trafo); - clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); - clipper.first->render_cut({ 1.0f, 0.37f, 0.0f, 1.0f }); - clipper.first->render_contour({ 1.f, 1.f, 1.f, 1.f }); + Geometry::Transformation trafo = inst_trafo * clipper.second; + trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); + clipper.first->set_plane(*m_clp); + clipper.first->set_transformation(trafo); + clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); + clipper.first->render_cut({ 1.0f, 0.37f, 0.0f, 1.0f }, &ignore_idxs_local); + clipper.first->render_contour({ 1.f, 1.f, 1.f, 1.f }, &ignore_idxs_local); + + // Now update the ignore idxs. Find the first element belonging to the next clipper, + // and remove everything before it and decrement everything by current number of contours. + const int num_of_contours = clipper.first->get_number_of_contours(); + ignore_idxs_local.erase(ignore_idxs_local.begin(), std::find_if(ignore_idxs_local.begin(), ignore_idxs_local.end(), [num_of_contours](size_t idx) { return idx >= num_of_contours; } )); + for (size_t& idx : ignore_idxs_local) + idx -= num_of_contours; } } @@ -415,6 +424,25 @@ bool ObjectClipper::has_valid_contour() const return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [](const auto& cl) { return cl.first->has_valid_contour(); }); } +std::vector ObjectClipper::point_per_contour() const +{ + std::vector pts; + + const SelectionInfo* sel_info = get_pool()->selection_info(); + const Geometry::Transformation inst_trafo = sel_info->model_object()->instances[sel_info->get_active_instance()]->get_transformation(); + + for (auto& clipper : m_clippers) { + Geometry::Transformation trafo = inst_trafo * clipper.second; + trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); + + // FIXME: do not assume just one clipper + pts = clipper.first->point_per_contour(); + //for (Vec3d& v : pts) + // v = trafo.get_matrix() * v; + } + return pts; +} + void ObjectClipper::set_position_by_ratio(double pos, bool keep_normal) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp index 4152cce51..e9d85de8d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp @@ -242,12 +242,13 @@ public: void set_normal(const Vec3d& dir); double get_position() const { return m_clp_ratio; } const ClippingPlane* get_clipping_plane(bool ignore_hide_clipped = false) const; - void render_cut() const; + void render_cut(const std::vector* ignore_idxs = nullptr) const; void set_position_by_ratio(double pos, bool keep_normal); void set_range_and_pos(const Vec3d& cpl_normal, double cpl_offset, double pos); void set_behavior(bool hide_clipped, bool fill_cut, double contour_width); int get_number_of_contours() const; + std::vector point_per_contour() const; int is_projection_inside_cut(const Vec3d& point_in) const; bool has_valid_contour() const; diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index cee684115..8e29a1c52 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -94,7 +94,7 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo) } } -void MeshClipper::render_cut(const ColorRGBA& color) +void MeshClipper::render_cut(const ColorRGBA& color, const std::vector* ignore_idxs) { if (! m_result) recalculate_triangles(); @@ -108,7 +108,10 @@ void MeshClipper::render_cut(const ColorRGBA& color) const Camera& camera = wxGetApp().plater()->get_camera(); shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - for (CutIsland& isl : m_result->cut_islands) { + for (size_t i=0; icut_islands.size(); ++i) { + if (ignore_idxs && std::binary_search(ignore_idxs->begin(), ignore_idxs->end(), i)) + continue; + CutIsland& isl = m_result->cut_islands[i]; isl.model.set_color(isl.disabled ? ColorRGBA(0.5f, 0.5f, 0.5f, 1.f) : color); isl.model.render(); } @@ -120,7 +123,7 @@ void MeshClipper::render_cut(const ColorRGBA& color) } -void MeshClipper::render_contour(const ColorRGBA& color) +void MeshClipper::render_contour(const ColorRGBA& color, const std::vector* ignore_idxs) { if (! m_result) recalculate_triangles(); @@ -135,7 +138,10 @@ void MeshClipper::render_contour(const ColorRGBA& color) const Camera& camera = wxGetApp().plater()->get_camera(); shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - for (CutIsland& isl : m_result->cut_islands) { + for (size_t i=0; icut_islands.size(); ++i) { + if (ignore_idxs && std::binary_search(ignore_idxs->begin(), ignore_idxs->end(), i)) + continue; + CutIsland& isl = m_result->cut_islands[i]; isl.model_expanded.set_color(isl.disabled ? ColorRGBA(1.f, 0.f, 0.f, 1.f) : color); isl.model_expanded.render(); } @@ -166,6 +172,20 @@ bool MeshClipper::has_valid_contour() const return m_result && std::any_of(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](const CutIsland& isl) { return !isl.expoly.empty(); }); } +std::vector MeshClipper::point_per_contour() const +{ + std::vector out; + if (!m_result || m_result->cut_islands.empty()) + return out; + + for (const CutIsland& isl : m_result->cut_islands) { + // FIXME: There might be holes ! + Vec2d c = unscale(isl.expoly.contour.centroid()); + out.emplace_back(m_result->trafo * Vec3d(c.x(), c.y(), 0.)); + } + return out; +} + void MeshClipper::recalculate_triangles() { diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index 257b500f9..be95daa15 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -115,13 +115,14 @@ public: // Render the triangulated cut. Transformation matrices should // be set in world coords. - void render_cut(const ColorRGBA& color); - void render_contour(const ColorRGBA& color); + void render_cut(const ColorRGBA& color, const std::vector* ignore_idxs = nullptr); + void render_contour(const ColorRGBA& color, const std::vector* ignore_idxs = nullptr); // Returns index of the contour which was clicked, -1 otherwise. int is_projection_inside_cut(const Vec3d& point) const; bool has_valid_contour() const; int get_number_of_contours() const { return m_result ? m_result->cut_islands.size() : 0; } + std::vector point_per_contour() const; private: void recalculate_triangles();