diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 86c126f8be..26053a7f8d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -729,8 +729,8 @@ public: bool init(); void post_event(wxEvent &&event); - void add_raycaster_for_picking(SceneRaycaster::EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) { - m_scene_raycaster.add_raycaster(type, id, raycaster, trafo); + std::shared_ptr add_raycaster_for_picking(SceneRaycaster::EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) { + return m_scene_raycaster.add_raycaster(type, id, raycaster, trafo); } void remove_raycasters_for_picking(SceneRaycaster::EType type, PickingId id) { m_scene_raycaster.remove_raycasters(type, id); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 7469c72257..ffb5e92f77 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -104,17 +104,17 @@ PickingModel &GLGizmoBase::Grabber::get_cube() return s_cube; } -void GLGizmoBase::Grabber::register_raycasters_for_picking(int id) +void GLGizmoBase::Grabber::register_raycasters_for_picking(PickingId id) { picking_id = id; - assert(elements_registered_for_picking == false); + // registration will happen on next call to render() } void GLGizmoBase::Grabber::unregister_raycasters_for_picking() { wxGetApp().plater()->canvas3D()->remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, picking_id); picking_id = -1; - elements_registered_for_picking = false; + raycasters = { nullptr }; } void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color) @@ -150,48 +150,48 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color) const Transform3d& view_matrix = camera.get_view_matrix(); const Matrix3d view_matrix_no_offset = view_matrix.matrix().block(0, 0, 3, 3); - auto render_extension = [&view_matrix, &view_matrix_no_offset, shader, register_for_picking = !elements_registered_for_picking, picking_id = picking_id](PickingModel &model, const Transform3d &model_matrix) { + auto render_extension = [&view_matrix, &view_matrix_no_offset, shader, this](int idx, PickingModel &model, const Transform3d &model_matrix) { shader->set_uniform("view_model_matrix", view_matrix * model_matrix); const Matrix3d view_normal_matrix = view_matrix_no_offset * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); shader->set_uniform("view_normal_matrix", view_normal_matrix); model.model.render(); - if (register_for_picking) { + if (raycasters[idx] == nullptr) { GLCanvas3D &canvas = *wxGetApp().plater()->canvas3D(); - canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *model.mesh_raycaster, model_matrix); + raycasters[idx] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *model.mesh_raycaster, model_matrix); + } else { + raycasters[idx]->set_transform(model_matrix); } }; if (extensions == EGrabberExtension::PosZ) { const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, Vec3d(0.75 * extension_size, 0.75 * extension_size, 2.0 * extension_size)); - render_extension(s_cone, model_matrix); + render_extension(0, s_cone, model_matrix); } else { const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, grabber_size * Vec3d::Ones()); - render_extension(s_cube, model_matrix); + render_extension(0, s_cube, model_matrix); const Transform3d extension_model_matrix_base = matrix * Geometry::assemble_transform(center, angles); const Vec3d extension_scale(0.75 * extension_size, 0.75 * extension_size, 3.0 * extension_size); if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) { - render_extension(s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0), extension_scale)); + render_extension(1, s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0), extension_scale)); } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) { - render_extension(s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0), extension_scale)); + render_extension(2, s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0), extension_scale)); } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) { - render_extension(s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0), extension_scale)); + render_extension(3, s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0), extension_scale)); } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) { - render_extension(s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0), extension_scale)); + render_extension(4, s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0), extension_scale)); } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) { - render_extension(s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitZ(), Vec3d::Zero(), extension_scale)); + render_extension(5, s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitZ(), Vec3d::Zero(), extension_scale)); } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) { - render_extension(s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0), extension_scale)); + render_extension(6, s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0), extension_scale)); } } - - elements_registered_for_picking = true; } GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) @@ -299,10 +299,10 @@ void GLGizmoBase::GizmoImguiSetNextWIndowPos(float &x, float y, int flag, float m_imgui->set_next_window_pos(x, y, flag, pivot_x, pivot_y); } -void GLGizmoBase::register_grabbers_for_picking(bool use_group_id) +void GLGizmoBase::register_grabbers_for_picking() { for (size_t i = 0; i < m_grabbers.size(); ++i) { - m_grabbers[i].register_raycasters_for_picking(use_group_id ? m_group_id : i); + m_grabbers[i].register_raycasters_for_picking((m_group_id >= 0) ? m_group_id : i); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index f7c4bf2eaa..6e6ff7efa5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -37,6 +37,7 @@ public: // Starting value for ids to avoid clashing with ids used by GLVolumes // (254 is choosen to leave some space for forward compatibility) static const unsigned int BASE_ID = 255 * 255 * 254; + static const unsigned int GRABBER_ELEMENTS_MAX_COUNT = 7; static float INV_ZOOM; @@ -86,8 +87,8 @@ protected: ColorRGBA hover_color{GRABBER_HOVER_COL}; EGrabberExtension extensions{ EGrabberExtension::None }; // the picking id shared by all the elements - int picking_id{ -1 }; - bool elements_registered_for_picking{ false }; + PickingId picking_id{ -1 }; + std::array, GRABBER_ELEMENTS_MAX_COUNT> raycasters = { nullptr }; Grabber() = default; ~Grabber(); @@ -98,7 +99,7 @@ protected: float get_dragging_half_size(float size) const; PickingModel &get_cube(); - void register_raycasters_for_picking(int id); + void register_raycasters_for_picking(PickingId id); void unregister_raycasters_for_picking(); private: @@ -212,7 +213,7 @@ public: int get_count() { return ++count; } std::string get_gizmo_name() { return on_get_name(); } - void register_raycasters_for_picking(bool use_group_id = false) { register_grabbers_for_picking(use_group_id); on_register_raycasters_for_picking(); } + void register_raycasters_for_picking() { register_grabbers_for_picking(); on_register_raycasters_for_picking(); } void unregister_raycasters_for_picking() { unregister_grabbers_for_picking(); on_unregister_raycasters_for_picking(); } protected: @@ -238,7 +239,7 @@ protected: void GizmoImguiEnd(); void GizmoImguiSetNextWIndowPos(float &x, float y, int flag, float pivot_x = 0.0f, float pivot_y = 0.0f); - void register_grabbers_for_picking(bool use_group_id = false); + void register_grabbers_for_picking(); void unregister_grabbers_for_picking(); virtual void on_register_raycasters_for_picking() {} virtual void on_unregister_raycasters_for_picking() {} diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 2ecb90641f..e6a2dd6973 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -515,7 +515,7 @@ void GLGizmoRotate3D::on_register_raycasters_for_picking() // the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account m_parent.set_raycaster_gizmos_on_top(true); for (GLGizmoRotate& g : m_gizmos) { - g.register_raycasters_for_picking(true); + g.register_raycasters_for_picking(); } } diff --git a/src/slic3r/GUI/SceneRaycaster.cpp b/src/slic3r/GUI/SceneRaycaster.cpp index 9a4f69b9d4..64bd55f7bc 100644 --- a/src/slic3r/GUI/SceneRaycaster.cpp +++ b/src/slic3r/GUI/SceneRaycaster.cpp @@ -31,31 +31,22 @@ SceneRaycaster::SceneRaycaster() { #endif // ENABLE_RAYCAST_PICKING_DEBUG } -void SceneRaycaster::add_raycaster(EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) +std::shared_ptr SceneRaycaster::add_raycaster(EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) { switch (type) { - case EType::Bed: { - m_bed.emplace_back(encode_id(type, id), raycaster, trafo); - break; - } - case EType::Volume: { - m_volumes.emplace_back(encode_id(type, id), raycaster, trafo); - break; - } - case EType::Gizmo: { - m_gizmos.emplace_back(encode_id(type, id), raycaster, trafo); - break; - } - default: { break; } + case EType::Bed: { return m_bed.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo)); } + case EType::Volume: { return m_volumes.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo)); } + case EType::Gizmo: { return m_gizmos.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo)); } + default: { assert(false); return nullptr; } }; } void SceneRaycaster::remove_raycasters(EType type, PickingId id) { - std::vector* raycasters = get_raycasters(type); + std::vector>* raycasters = get_raycasters(type); auto it = raycasters->begin(); while (it != raycasters->end()) { - if (it->get_id() == encode_id(type, id)) + if ((*it)->get_id() == encode_id(type, id)) it = raycasters->erase(it); else ++it; @@ -72,24 +63,24 @@ void SceneRaycaster::remove_raycasters(EType type) }; } -void SceneRaycaster::set_raycaster_active_state(EType type, PickingId id, bool active) +void SceneRaycaster::remove_raycaster(std::shared_ptr item) { - std::vector* raycasters = get_raycasters(type); - for (SceneRaycasterItem& item : *raycasters) { - if (item.get_id() == encode_id(type, id)) { - item.set_active(active); - break; + for (auto it = m_bed.begin(); it != m_bed.end(); ++it) { + if (*it == item) { + m_bed.erase(it); + return; } } -} - -void SceneRaycaster::set_raycaster_transform(EType type, PickingId id, const Transform3d& trafo) -{ - std::vector* raycasters = get_raycasters(type); - for (SceneRaycasterItem& item : *raycasters) { - if (item.get_id() == encode_id(type, id)) { - item.set_transform(trafo); - break; + for (auto it = m_volumes.begin(); it != m_volumes.end(); ++it) { + if (*it == item) { + m_volumes.erase(it); + return; + } + } + for (auto it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { + if (*it == item) { + m_gizmos.erase(it); + return; } } } @@ -113,15 +104,15 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came auto test_raycasters = [&](EType type) { const ClippingPlane* clip_plane = (clipping_plane != nullptr && type == EType::Volume) ? clipping_plane : nullptr; - const std::vector* raycasters = get_raycasters(type); + std::vector>* raycasters = get_raycasters(type); HitResult current_hit = { type }; - for (const SceneRaycasterItem& item : *raycasters) { - if (!item.is_active()) + for (std::shared_ptr item : *raycasters) { + if (!item->is_active()) continue; - current_hit.raycaster_id = item.get_id(); - const Transform3d& trafo = item.get_transform(); - if (item.get_raycaster()->closest_hit(mouse_pos, trafo, camera, current_hit.position, current_hit.normal, clip_plane)) { + current_hit.raycaster_id = item->get_id(); + const Transform3d& trafo = item->get_transform(); + if (item->get_raycaster()->closest_hit(mouse_pos, trafo, camera, current_hit.position, current_hit.normal, clip_plane)) { current_hit.position = (trafo * current_hit.position.cast()).cast(); if (is_closest(camera, current_hit.position)) { const Transform3d matrix = camera.get_view_matrix() * trafo; @@ -180,14 +171,15 @@ void SceneRaycaster::render_hit(const Camera& camera) } #endif // ENABLE_RAYCAST_PICKING_DEBUG -std::vector* SceneRaycaster::get_raycasters(EType type) +std::vector>* SceneRaycaster::get_raycasters(EType type) { - std::vector* ret = nullptr; + std::vector>* ret = nullptr; switch (type) { case EType::Bed: { ret = &m_bed; break; } case EType::Volume: { ret = &m_volumes; break; } case EType::Gizmo: { ret = &m_gizmos; break; } + default: { break; } } assert(ret != nullptr); return ret; diff --git a/src/slic3r/GUI/SceneRaycaster.hpp b/src/slic3r/GUI/SceneRaycaster.hpp index 1832ffc558..d0b47dbc75 100644 --- a/src/slic3r/GUI/SceneRaycaster.hpp +++ b/src/slic3r/GUI/SceneRaycaster.hpp @@ -64,9 +64,9 @@ public: }; private: - std::vector m_bed; - std::vector m_volumes; - std::vector m_gizmos; + std::vector> m_bed; + std::vector> m_volumes; + std::vector> m_gizmos; // When set to true, if checking gizmos returns a valid hit, // the search is not performed on other types @@ -81,12 +81,10 @@ private: public: SceneRaycaster(); - void add_raycaster(EType type, PickingId picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo); + std::shared_ptr add_raycaster(EType type, PickingId picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo); void remove_raycasters(EType type, PickingId id); void remove_raycasters(EType type); - - void set_raycaster_active_state(EType type, PickingId picking_id, bool active); - void set_raycaster_transform(EType type, PickingId picking_id, const Transform3d& trafo); + void remove_raycaster(std::shared_ptr item); void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; } @@ -101,7 +99,7 @@ public: #endif // ENABLE_RAYCAST_PICKING_DEBUG private: - std::vector* get_raycasters(EType type); + std::vector>* get_raycasters(EType type); static PickingId encode_id(EType type, PickingId id); static PickingId decode_id(EType type, PickingId id);