diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c40d05aa7..2a571364c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1958,12 +1958,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re m_hover_volume_idxs.clear(); -#if ENABLE_RAYCAST_PICKING - GLGizmoBase* curr_gizmo = m_gizmos.get_current(); - if (curr_gizmo != nullptr) - curr_gizmo->unregister_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING - struct ModelVolumeState { ModelVolumeState(const GLVolume* volume) : model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {} @@ -2416,6 +2410,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } // refresh gizmo elements raycasters for picking + GLGizmoBase* curr_gizmo = m_gizmos.get_current(); + if (curr_gizmo != nullptr) + curr_gizmo->unregister_raycasters_for_picking(); m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Gizmo); if (curr_gizmo != nullptr && !m_selection.is_empty()) curr_gizmo->register_raycasters_for_picking(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 9c89f3e53..8835285ec 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -673,6 +673,10 @@ public: m_scene_raycaster.remove_raycasters(type); } + std::vector>* get_raycasters_for_picking(SceneRaycaster::EType type) { + return m_scene_raycaster.get_raycasters(type); + } + void set_raycaster_gizmos_on_top(bool value) { m_scene_raycaster.set_gizmos_on_top(value); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index f559217c1..2a517b74b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -55,6 +55,12 @@ void GLGizmoHollow::data_changed() } if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh()) m_holes_in_drilled_mesh = mo->sla_drain_holes; +#if ENABLE_RAYCAST_PICKING + if (m_raycasters.empty()) + on_register_raycasters_for_picking(); + else + update_raycasters_for_picking_transform(); +#endif // ENABLE_RAYCAST_PICKING } } @@ -62,8 +68,16 @@ void GLGizmoHollow::data_changed() void GLGizmoHollow::on_render() { +#if ENABLE_RAYCAST_PICKING + if (!m_cylinder.model.is_initialized()) { + indexed_triangle_set its = its_make_cylinder(1.0, 1.0); + m_cylinder.model.init_from(its); + m_cylinder.mesh_raycaster = std::make_unique(std::make_shared(std::move(its))); + } +#else if (!m_cylinder.is_initialized()) m_cylinder.init_from(its_make_cylinder(1.0, 1.0)); +#endif // ENABLE_RAYCAST_PICKING const Selection& selection = m_parent.get_selection(); const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info(); @@ -80,7 +94,11 @@ void GLGizmoHollow::on_render() glsafe(::glEnable(GL_DEPTH_TEST)); if (selection.is_from_single_instance()) +#if ENABLE_RAYCAST_PICKING + render_points(selection); +#else render_points(selection, false); +#endif // ENABLE_RAYCAST_PICKING m_selection_rectangle.render(m_parent); m_c->object_clipper()->render_cut(); @@ -89,8 +107,29 @@ void GLGizmoHollow::on_render() glsafe(::glDisable(GL_BLEND)); } +#if ENABLE_RAYCAST_PICKING +void GLGizmoHollow::on_register_raycasters_for_picking() +{ + assert(m_raycasters.empty()); -#if !ENABLE_RAYCAST_PICKING + set_sla_auxiliary_volumes_picking_state(false); + const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info(); + if (info != nullptr && info->model_object()->sla_drain_holes.size() > 0) { + const sla::DrainHoles& drain_holes = info->model_object()->sla_drain_holes; + for (int i = 0; i < (int)drain_holes.size(); ++i) { + m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_cylinder.mesh_raycaster, Transform3d::Identity())); + } + update_raycasters_for_picking_transform(); + } +} + +void GLGizmoHollow::on_unregister_raycasters_for_picking() +{ + m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo); + m_raycasters.clear(); + set_sla_auxiliary_volumes_picking_state(true); +} +#else void GLGizmoHollow::on_render_for_picking() { const Selection& selection = m_parent.get_selection(); @@ -101,12 +140,20 @@ void GLGizmoHollow::on_render_for_picking() glsafe(::glEnable(GL_DEPTH_TEST)); render_points(selection, true); } -#endif // !ENABLE_RAYCAST_PICKING +#endif // ENABLE_RAYCAST_PICKING +#if ENABLE_RAYCAST_PICKING +void GLGizmoHollow::render_points(const Selection& selection) +#else void GLGizmoHollow::render_points(const Selection& selection, bool picking) +#endif // ENABLE_RAYCAST_PICKING { #if ENABLE_LEGACY_OPENGL_REMOVAL +#if ENABLE_RAYCAST_PICKING + GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); +#else GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light"); +#endif // ENABLE_RAYCAST_PICKING if (shader == nullptr) return; @@ -152,13 +199,22 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) const sla::DrainHole& drain_hole = drain_holes[i]; const bool point_selected = m_selected[i]; +#if ENABLE_RAYCAST_PICKING + const bool clipped = is_mesh_point_clipped(drain_hole.pos.cast()); + m_raycasters[i]->set_active(!clipped); + if (clipped) + continue; +#else if (is_mesh_point_clipped(drain_hole.pos.cast())) continue; +#endif // ENABLE_RAYCAST_PICKING // First decide about the color of the point. +#if !ENABLE_RAYCAST_PICKING if (picking) render_color = picking_color_component(i); else { +#endif // !ENABLE_RAYCAST_PICKING if (size_t(m_hover_id) == i) render_color = ColorRGBA::CYAN(); else if (m_c->hollowed_mesh() && @@ -168,10 +224,16 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) } else // neither hover nor picking render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); +#if !ENABLE_RAYCAST_PICKING } +#endif // !ENABLE_RAYCAST_PICKING #if ENABLE_LEGACY_OPENGL_REMOVAL +#if ENABLE_RAYCAST_PICKING + m_cylinder.model.set_color(render_color); +#else m_cylinder.set_color(render_color); +#endif // ENABLE_RAYCAST_PICKING // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. const Transform3d hole_matrix = Geometry::assemble_transform(drain_hole.pos.cast()) * instance_scaling_matrix_inverse; #else @@ -200,7 +262,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); #endif // ENABLE_LEGACY_OPENGL_REMOVAL +#if ENABLE_RAYCAST_PICKING + m_cylinder.model.render(); +#else m_cylinder.render(); +#endif // ENABLE_RAYCAST_PICKING if (vol->is_left_handed()) glsafe(::glFrontFace(GL_CCW)); @@ -327,6 +393,10 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos assert(m_selected.size() == mo->sla_drain_holes.size()); m_parent.set_as_dirty(); m_wait_for_up_event = true; +#if ENABLE_RAYCAST_PICKING + on_unregister_raycasters_for_picking(); + on_register_raycasters_for_picking(); +#endif // ENABLE_RAYCAST_PICKING } else return false; @@ -520,6 +590,47 @@ void GLGizmoHollow::hollow_mesh(bool postpone_error_messages) }); } +#if ENABLE_RAYCAST_PICKING +void GLGizmoHollow::set_sla_auxiliary_volumes_picking_state(bool state) +{ + std::vector>* raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume); + if (raycasters != nullptr) { + const Selection& selection = m_parent.get_selection(); + const Selection::IndicesList ids = selection.get_volume_idxs(); + for (unsigned int id : ids) { + const GLVolume* v = selection.get_volume(id); + if (v->is_sla_pad() || v->is_sla_support()) { + auto it = std::find_if(raycasters->begin(), raycasters->end(), [v](std::shared_ptr item) { return item->get_raycaster() == v->mesh_raycaster.get(); }); + if (it != raycasters->end()) + (*it)->set_active(state); + } + } + } +} + +void GLGizmoHollow::update_raycasters_for_picking_transform() +{ + const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info(); + if (info != nullptr) { + const sla::DrainHoles& drain_holes = info->model_object()->sla_drain_holes; + if (!drain_holes.empty()) { + const GLVolume* vol = m_parent.get_selection().get_first_volume(); + const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_scaling_factor_matrix().inverse(); + + for (size_t i = 0; i < drain_holes.size(); ++i) { + const sla::DrainHole& drain_hole = drain_holes[i]; + const Transform3d hole_matrix = Geometry::translation_transform(drain_hole.pos.cast()) * instance_scaling_matrix_inverse; + Eigen::Quaterniond q; + q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); + const Eigen::AngleAxisd aa(q); + const Transform3d matrix = vol->world_matrix() * hole_matrix * Transform3d(aa.toRotationMatrix()) * + Geometry::translation_transform(-drain_hole.height * Vec3d::UnitZ()) * Geometry::scale_transform(Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); + m_raycasters[i]->set_transform(matrix); + } + } + } +} +#endif // ENABLE_RAYCAST_PICKING std::vector> GLGizmoHollow::get_config_options(const std::vector& keys) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index 59d64c522..3c16d9288 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -28,8 +28,7 @@ private: public: GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - virtual ~GLGizmoHollow() = default; - void data_changed() override; + void data_changed() override; bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); void delete_selected_points(); bool is_selection_rectangle_dragging() const { @@ -43,20 +42,37 @@ public: /// Keep information about mouse click /// Return True when use the information otherwise False. bool on_mouse(const wxMouseEvent &mouse_event) override; -private: + +protected: bool on_init() override; void on_render() override; -#if !ENABLE_RAYCAST_PICKING +#if ENABLE_RAYCAST_PICKING + virtual void on_register_raycasters_for_picking() override; + virtual void on_unregister_raycasters_for_picking() override; +#else void on_render_for_picking() override; -#endif // !ENABLE_RAYCAST_PICKING +#endif // ENABLE_RAYCAST_PICKING +private: +#if ENABLE_RAYCAST_PICKING + void render_points(const Selection& selection); +#else void render_points(const Selection& selection, bool picking = false); +#endif // ENABLE_RAYCAST_PICKING void hollow_mesh(bool postpone_error_messages = false); - bool unsaved_changes() const; +#if ENABLE_RAYCAST_PICKING + void set_sla_auxiliary_volumes_picking_state(bool state); + void update_raycasters_for_picking_transform(); +#endif // ENABLE_RAYCAST_PICKING ObjectID m_old_mo_id = -1; +#if ENABLE_RAYCAST_PICKING + PickingModel m_cylinder; + std::vector> m_raycasters; +#else GLModel m_cylinder; +#endif // ENABLE_RAYCAST_PICKING float m_new_hole_radius = 2.f; // Size of a new hole. float m_new_hole_height = 6.f; diff --git a/src/slic3r/GUI/SceneRaycaster.hpp b/src/slic3r/GUI/SceneRaycaster.hpp index c08061b52..fb5aee88e 100644 --- a/src/slic3r/GUI/SceneRaycaster.hpp +++ b/src/slic3r/GUI/SceneRaycaster.hpp @@ -88,6 +88,8 @@ public: void remove_raycasters(EType type); void remove_raycaster(std::shared_ptr item); + std::vector>* get_raycasters(EType type); + void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; } HitResult hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane = nullptr); @@ -101,8 +103,6 @@ public: #endif // ENABLE_RAYCAST_PICKING_DEBUG private: - std::vector>* get_raycasters(EType type); - static PickingId encode_id(EType type, PickingId id); static PickingId decode_id(EType type, PickingId id); static PickingId base_id(EType type);