diff --git a/src/libslic3r/Color.hpp b/src/libslic3r/Color.hpp index 183705c4af..efde3fe4da 100644 --- a/src/libslic3r/Color.hpp +++ b/src/libslic3r/Color.hpp @@ -133,41 +133,41 @@ public: static const ColorRGBA Z() { return { 0.0f, 0.0f, 0.75f, 1.0f }; } }; -extern ColorRGB operator * (float value, const ColorRGB& other); -extern ColorRGBA operator * (float value, const ColorRGBA& other); +ColorRGB operator * (float value, const ColorRGB& other); +ColorRGBA operator * (float value, const ColorRGBA& other); -extern ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t); -extern ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t); +ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t); +ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t); -extern ColorRGB complementary(const ColorRGB& color); -extern ColorRGBA complementary(const ColorRGBA& color); +ColorRGB complementary(const ColorRGB& color); +ColorRGBA complementary(const ColorRGBA& color); -extern ColorRGB saturate(const ColorRGB& color, float factor); -extern ColorRGBA saturate(const ColorRGBA& color, float factor); +ColorRGB saturate(const ColorRGB& color, float factor); +ColorRGBA saturate(const ColorRGBA& color, float factor); -extern ColorRGB opposite(const ColorRGB& color); -extern ColorRGB opposite(const ColorRGB& a, const ColorRGB& b); +ColorRGB opposite(const ColorRGB& color); +ColorRGB opposite(const ColorRGB& a, const ColorRGB& b); -extern bool can_decode_color(const std::string& color); +bool can_decode_color(const std::string& color); -extern bool decode_color(const std::string& color_in, ColorRGB& color_out); -extern bool decode_color(const std::string& color_in, ColorRGBA& color_out); +bool decode_color(const std::string& color_in, ColorRGB& color_out); +bool decode_color(const std::string& color_in, ColorRGBA& color_out); -extern bool decode_colors(const std::vector& colors_in, std::vector& colors_out); -extern bool decode_colors(const std::vector& colors_in, std::vector& colors_out); +bool decode_colors(const std::vector& colors_in, std::vector& colors_out); +bool decode_colors(const std::vector& colors_in, std::vector& colors_out); -extern std::string encode_color(const ColorRGB& color); -extern std::string encode_color(const ColorRGBA& color); +std::string encode_color(const ColorRGB& color); +std::string encode_color(const ColorRGBA& color); -extern ColorRGB to_rgb(const ColorRGBA& other_rgba); -extern ColorRGBA to_rgba(const ColorRGB& other_rgb); -extern ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha); +ColorRGB to_rgb(const ColorRGBA& other_rgba); +ColorRGBA to_rgba(const ColorRGB& other_rgb); +ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha); -extern ColorRGBA picking_decode(unsigned int id); -extern unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b); +ColorRGBA picking_decode(unsigned int id); +unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b); // Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components // were not interpolated by alpha blending or multi sampling. -extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue); +unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue); } // namespace Slic3r diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 202912f3d7..88c61ac8b1 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -704,7 +704,6 @@ void Bed3D::render_custom(GLCanvas3D& canvas, const Transform3d& view_matrix, co void Bed3D::render_default(bool bottom, const Transform3d& view_matrix, const Transform3d& projection_matrix) { - bool picking = false; m_texture.reset(); update_bed_triangles(); diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 420ac15c9e..7206b5e6c4 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -106,6 +106,78 @@ void Camera::select_view(const std::string& direction) } } +double Camera::get_near_left() const +{ + switch (m_type) + { + case EType::Perspective: + return m_frustrum_zs.first * (m_projection_matrix.matrix()(0, 2) - 1.0) / m_projection_matrix.matrix()(0, 0); + default: + case EType::Ortho: + return -1.0 / m_projection_matrix.matrix()(0, 0) - 0.5 * m_projection_matrix.matrix()(0, 0) * m_projection_matrix.matrix()(0, 3); + } +} + +double Camera::get_near_right() const +{ + switch (m_type) + { + case EType::Perspective: + return m_frustrum_zs.first * (m_projection_matrix.matrix()(0, 2) + 1.0) / m_projection_matrix.matrix()(0, 0); + default: + case EType::Ortho: + return 1.0 / m_projection_matrix.matrix()(0, 0) - 0.5 * m_projection_matrix.matrix()(0, 0) * m_projection_matrix.matrix()(0, 3); + } +} + +double Camera::get_near_top() const +{ + switch (m_type) + { + case EType::Perspective: + return m_frustrum_zs.first * (m_projection_matrix.matrix()(1, 2) + 1.0) / m_projection_matrix.matrix()(1, 1); + default: + case EType::Ortho: + return 1.0 / m_projection_matrix.matrix()(1, 1) - 0.5 * m_projection_matrix.matrix()(1, 1) * m_projection_matrix.matrix()(1, 3); + } +} + +double Camera::get_near_bottom() const +{ + switch (m_type) + { + case EType::Perspective: + return m_frustrum_zs.first * (m_projection_matrix.matrix()(1, 2) - 1.0) / m_projection_matrix.matrix()(1, 1); + default: + case EType::Ortho: + return -1.0 / m_projection_matrix.matrix()(1, 1) - 0.5 * m_projection_matrix.matrix()(1, 1) * m_projection_matrix.matrix()(1, 3); + } +} + +double Camera::get_near_width() const +{ + switch (m_type) + { + case EType::Perspective: + return 2.0 * m_frustrum_zs.first / m_projection_matrix.matrix()(0, 0); + default: + case EType::Ortho: + return 2.0 / m_projection_matrix.matrix()(0, 0); + } +} + +double Camera::get_near_height() const +{ + switch (m_type) + { + case EType::Perspective: + return 2.0 * m_frustrum_zs.first / m_projection_matrix.matrix()(1, 1); + default: + case EType::Ortho: + return 2.0 / m_projection_matrix.matrix()(1, 1); + } +} + double Camera::get_fov() const { switch (m_type) @@ -118,12 +190,16 @@ double Camera::get_fov() const }; } -void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h) +void Camera::set_viewport(int x, int y, unsigned int w, unsigned int h) { - glsafe(::glViewport(0, 0, w, h)); m_viewport = { 0, 0, int(w), int(h) }; } +void Camera::apply_viewport() const +{ + glsafe(::glViewport(m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3])); +} + void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double far_z) { double w = 0.0; @@ -163,30 +239,33 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa } } + apply_projection(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second); +} + +void Camera::apply_projection(double left, double right, double bottom, double top, double near_z, double far_z) +{ + assert(left != right && bottom != top && near_z != far_z); + const double inv_dx = 1.0 / (right - left); + const double inv_dy = 1.0 / (top - bottom); + const double inv_dz = 1.0 / (far_z - near_z); + switch (m_type) { default: case EType::Ortho: { - const double dz = m_frustrum_zs.second - m_frustrum_zs.first; - const double zz = m_frustrum_zs.first + m_frustrum_zs.second; - m_projection_matrix.matrix() << 1.0 / w, 0.0, 0.0, 0.0, - 0.0, 1.0 / h, 0.0, 0.0, - 0.0, 0.0, -2.0 / dz, -zz / dz, - 0.0, 0.0, 0.0, 1.0; + m_projection_matrix.matrix() << 2.0 * inv_dx, 0.0, 0.0, -(left + right) * inv_dx, + 0.0, 2.0 * inv_dy, 0.0, -(bottom + top) * inv_dy, + 0.0, 0.0, -2.0 * inv_dz, -(near_z + far_z) * inv_dz, + 0.0, 0.0, 0.0, 1.0; break; } case EType::Perspective: { - const double n = m_frustrum_zs.first; - const double f = m_frustrum_zs.second; - const double dz = f - n; - const double zz = n + f; - const double fn = n * f; - m_projection_matrix.matrix() << n / w, 0.0, 0.0, 0.0, - 0.0, n / h, 0.0, 0.0, - 0.0, 0.0, -zz / dz, -2.0 * fn / dz, - 0.0, 0.0, -1.0, 0.0; + m_projection_matrix.matrix() << 2.0 * near_z * inv_dx, 0.0, (left + right) * inv_dx, 0.0, + 0.0, 2.0 * near_z * inv_dy, (bottom + top) * inv_dy, 0.0, + 0.0, 0.0, -(near_z + far_z) * inv_dz, -2.0 * near_z * far_z * inv_dz, + 0.0, 0.0, -1.0, 0.0; break; } } diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 2fdd16461e..cfed47884c 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -107,13 +107,23 @@ public: double get_far_z() const { return m_frustrum_zs.second; } const std::pair& get_z_range() const { return m_frustrum_zs; } + double get_near_left() const; + double get_near_right() const; + double get_near_top() const; + double get_near_bottom() const; + double get_near_width() const; + double get_near_height() const; + double get_fov() const; - void apply_viewport(int x, int y, unsigned int w, unsigned int h); + void set_viewport(int x, int y, unsigned int w, unsigned int h); + void apply_viewport() const; // Calculates and applies the projection matrix tighting the frustrum z range around the given box. // If larger z span is needed, pass the desired values of near and far z (negative values are ignored) void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0); + void apply_projection(double left, double right, double bottom, double top, double near_z, double far_z); + void zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultZoomToBoxMarginFactor); void zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor = DefaultZoomToVolumesMarginFactor); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 948632e159..edb1fade57 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1305,7 +1305,8 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai #if 1 Camera camera; - camera.apply_viewport(0,0,thumbnail_data.width, thumbnail_data.height); + camera.set_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); + camera.apply_viewport(); camera.set_scene_box(plate_box); camera.set_type(Camera::EType::Ortho); camera.set_target(center); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index af0c517f10..5cd88b1534 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1787,7 +1787,8 @@ void GLCanvas3D::render(bool only_init) // and the viewport was set incorrectly, leading to tripping glAsserts further down // the road (in apply_projection). That's why the minimum size is forced to 10. Camera& camera = wxGetApp().plater()->get_camera(); - camera.apply_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height())); + camera.set_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height())); + camera.apply_viewport(); if (camera.requires_zoom_to_bed) { zoom_to_bed(); @@ -1896,7 +1897,7 @@ void GLCanvas3D::render(bool only_init) _render_current_gizmo(); #if ENABLE_RAYCAST_PICKING_DEBUG - if (m_picking_enabled && !m_mouse.dragging) + if (m_picking_enabled && !m_mouse.dragging && !m_gizmos.is_dragging() && !m_rectangle_selection.is_dragging()) m_scene_raycaster.render_hit(camera); #endif // ENABLE_RAYCAST_PICKING_DEBUG @@ -5540,7 +5541,8 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const //BBS modify scene box to plate scene bounding box //plate_build_volume.min(2) = - plate_build_volume.max(2); camera.set_scene_box(plate_build_volume); - camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); + camera.set_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); + camera.apply_viewport(); //BoundingBoxf3 plate_box = plate->get_bounding_box(false); //plate_box.min.z() = 0.0; @@ -5911,7 +5913,7 @@ void GLCanvas3D::render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT // restore the default framebuffer size to avoid flickering on the 3D scene - //wxGetApp().plater()->get_camera().apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height()); + //wxGetApp().plater()->get_camera().apply_viewport(); } //BBS: GUI refractor @@ -6412,11 +6414,13 @@ void GLCanvas3D::_refresh_if_shown_on_screen() void GLCanvas3D::_picking_pass() { - if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX)) { + if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX) && !m_gizmos.is_dragging()) { +#if ENABLE_RAYCAST_PICKING_DEBUG ImGuiWrapper& imgui = *wxGetApp().imgui(); imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize); imgui.text("Picking disabled"); imgui.end(); +#endif // ENABLE_RAYCAST_PICKING_DEBUG return; } @@ -6502,6 +6506,7 @@ void GLCanvas3D::_picking_pass() object_type = "Volume"; break; } + default: { break; } } char buf[1024]; if (hit.type != SceneRaycaster::EType::None) { @@ -6536,6 +6541,56 @@ void GLCanvas3D::_rectangular_selection_picking_pass() std::set idxs; if (m_picking_enabled) { + const size_t width = std::max(m_rectangle_selection.get_width(), 1); + const size_t height = std::max(m_rectangle_selection.get_height(), 1); + + const OpenGLManager::EFramebufferType framebuffers_type = OpenGLManager::get_framebuffers_type(); + bool use_framebuffer = framebuffers_type != OpenGLManager::EFramebufferType::Unknown; + + GLuint render_fbo = 0; + GLuint render_tex = 0; + GLuint render_depth = 0; + if (use_framebuffer) { + // setup a framebuffer which covers only the selection rectangle + if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) { + glsafe(::glGenFramebuffers(1, &render_fbo)); + glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo)); + } + else { + glsafe(::glGenFramebuffersEXT(1, &render_fbo)); + glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo)); + } + glsafe(::glGenTextures(1, &render_tex)); + glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex)); + glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) { + glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0)); + glsafe(::glGenRenderbuffers(1, &render_depth)); + glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth)); + glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height)); + glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth)); + } + else { + glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0)); + glsafe(::glGenRenderbuffersEXT(1, &render_depth)); + glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth)); + glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height)); + glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth)); + } + const GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 }; + glsafe(::glDrawBuffers(1, drawBufs)); + if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) { + if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + use_framebuffer = false; + } + else { + if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) + use_framebuffer = false; + } + } + if (m_multisample_allowed) // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. glsafe(::glDisable(GL_MULTISAMPLE)); @@ -6545,20 +6600,48 @@ void GLCanvas3D::_rectangular_selection_picking_pass() glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); - _render_volumes_for_picking(); + Camera& main_camera = wxGetApp().plater()->get_camera(); + Camera framebuffer_camera; + Camera* camera = &main_camera; + if (use_framebuffer) { + // setup a camera which covers only the selection rectangle + const std::array& viewport = camera->get_viewport(); + const double near_left = camera->get_near_left(); + const double near_bottom = camera->get_near_bottom(); + const double near_width = camera->get_near_width(); + const double near_height = camera->get_near_height(); + + const double ratio_x = near_width / double(viewport[2]); + const double ratio_y = near_height / double(viewport[3]); + + const double rect_near_left = near_left + double(m_rectangle_selection.get_left()) * ratio_x; + const double rect_near_bottom = near_bottom + (double(viewport[3]) - double(m_rectangle_selection.get_bottom())) * ratio_y; + double rect_near_right = near_left + double(m_rectangle_selection.get_right()) * ratio_x; + double rect_near_top = near_bottom + (double(viewport[3]) - double(m_rectangle_selection.get_top())) * ratio_y; + + if (rect_near_left == rect_near_right) + rect_near_right = rect_near_left + ratio_x; + if (rect_near_bottom == rect_near_top) + rect_near_top = rect_near_bottom + ratio_y; + + framebuffer_camera.look_at(camera->get_position(), camera->get_target(), camera->get_dir_up()); + framebuffer_camera.apply_projection(rect_near_left, rect_near_right, rect_near_bottom, rect_near_top, camera->get_near_z(), camera->get_far_z()); + framebuffer_camera.set_viewport(0, 0, width, height); + framebuffer_camera.apply_viewport(); + camera = &framebuffer_camera; + } + + _render_volumes_for_picking(*camera); //BBS: remove the bed picking logic //_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); if (m_multisample_allowed) glsafe(::glEnable(GL_MULTISAMPLE)); - int width = std::max((int)m_rectangle_selection.get_width(), 1); - int height = std::max((int)m_rectangle_selection.get_height(), 1); - int px_count = width * height; + const size_t px_count = width * height; - int left = (int)m_rectangle_selection.get_left(); - int top = get_canvas_size().get_height() - (int)m_rectangle_selection.get_top(); - if (left >= 0 && top >= 0) { + const size_t left = use_framebuffer ? 0 : (size_t)m_rectangle_selection.get_left(); + const size_t top = use_framebuffer ? 0 : (size_t)get_canvas_size().get_height() - (size_t)m_rectangle_selection.get_top(); #define USE_PARALLEL 1 #if USE_PARALLEL struct Pixel @@ -6602,7 +6685,26 @@ void GLCanvas3D::_rectangular_selection_picking_pass() idxs.insert(volume_id); } #endif // USE_PARALLEL - } + if (camera != &main_camera) + main_camera.apply_viewport(); + + if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) { + glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0)); + if (render_depth != 0) + glsafe(::glDeleteRenderbuffers(1, &render_depth)); + if (render_fbo != 0) + glsafe(::glDeleteFramebuffers(1, &render_fbo)); + } + else if (framebuffers_type == OpenGLManager::EFramebufferType::Ext) { + glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + if (render_depth != 0) + glsafe(::glDeleteRenderbuffersEXT(1, &render_depth)); + if (render_fbo != 0) + glsafe(::glDeleteFramebuffersEXT(1, &render_fbo)); + } + + if (render_tex != 0) + glsafe(::glDeleteTextures(1, &render_tex)); } m_hover_volume_idxs.assign(idxs.begin(), idxs.end()); @@ -7194,7 +7296,7 @@ void GLCanvas3D::_render_style_editor() ImGui::End(); } -void GLCanvas3D::_render_volumes_for_picking() const +void GLCanvas3D::_render_volumes_for_picking(const Camera& camera) const { GLShaderProgram* shader = wxGetApp().get_shader("flat_clip"); if (shader == nullptr) @@ -7203,7 +7305,7 @@ void GLCanvas3D::_render_volumes_for_picking() const // do not cull backfaces to show broken geometry, if any glsafe(::glDisable(GL_CULL_FACE)); - const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix(); + const Transform3d& view_matrix = camera.get_view_matrix(); for (size_t type = 0; type < 2; ++ type) { GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::ERenderType::Opaque : GLVolumeCollection::ERenderType::Transparent, view_matrix); for (const GLVolumeWithIdAndZ& volume : to_render) @@ -7216,8 +7318,7 @@ void GLCanvas3D::_render_volumes_for_picking() const //const unsigned int id = 1 + volume.second.first; volume.first->model.set_color(picking_decode(id)); shader->start_using(); - const Camera& camera = wxGetApp().plater()->get_camera(); - shader->set_uniform("view_model_matrix", camera.get_view_matrix() * volume.first->world_matrix()); + shader->set_uniform("view_model_matrix", view_matrix * volume.first->world_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("volume_world_matrix", volume.first->world_matrix()); shader->set_uniform("z_range", m_volumes.get_z_range()); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 407a2ebb47..db1f004a81 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -725,16 +725,20 @@ public: bool init(); void post_event(wxEvent &&event); - std::shared_ptr add_raycaster_for_picking(SceneRaycaster::EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) { + std::shared_ptr add_raycaster_for_picking(SceneRaycaster::EType type, int 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) { + void remove_raycasters_for_picking(SceneRaycaster::EType type, int id) { m_scene_raycaster.remove_raycasters(type, id); } void remove_raycasters_for_picking(SceneRaycaster::EType type) { 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); } @@ -1144,7 +1148,7 @@ private: void _check_and_update_toolbar_icon_scale(); void _render_overlays(); void _render_style_editor(); - void _render_volumes_for_picking() const; + void _render_volumes_for_picking(const Camera& camera) const; void _render_current_gizmo() const; void _render_gizmos_overlay(); void _render_main_toolbar(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index ffb5e92f77..6b3eede5c3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -104,7 +104,7 @@ PickingModel &GLGizmoBase::Grabber::get_cube() return s_cube; } -void GLGizmoBase::Grabber::register_raycasters_for_picking(PickingId id) +void GLGizmoBase::Grabber::register_raycasters_for_picking(int id) { picking_id = id; // registration will happen on next call to render() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 6e6ff7efa5..d85e5583e4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -87,7 +87,7 @@ protected: ColorRGBA hover_color{GRABBER_HOVER_COL}; EGrabberExtension extensions{ EGrabberExtension::None }; // the picking id shared by all the elements - PickingId picking_id{ -1 }; + int picking_id{ -1 }; std::array, GRABBER_ELEMENTS_MAX_COUNT> raycasters = { nullptr }; Grabber() = default; @@ -99,7 +99,7 @@ protected: float get_dragging_half_size(float size) const; PickingModel &get_cube(); - void register_raycasters_for_picking(PickingId id); + void register_raycasters_for_picking(int id); void unregister_raycasters_for_picking(); private: diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp index 61d34ba492..b1892e5d06 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -26,7 +26,7 @@ private: PickingModel vbo; Vec3d normal; float area; - PickingId picking_id{ -1 }; + int picking_id{ -1 }; }; // This holds information to decide whether recalculation is necessary: diff --git a/src/slic3r/GUI/SceneRaycaster.cpp b/src/slic3r/GUI/SceneRaycaster.cpp index 64bd55f7bc..faf44a1675 100644 --- a/src/slic3r/GUI/SceneRaycaster.cpp +++ b/src/slic3r/GUI/SceneRaycaster.cpp @@ -31,7 +31,7 @@ SceneRaycaster::SceneRaycaster() { #endif // ENABLE_RAYCAST_PICKING_DEBUG } -std::shared_ptr SceneRaycaster::add_raycaster(EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) +std::shared_ptr SceneRaycaster::add_raycaster(EType type, int id, const MeshRaycaster& raycaster, const Transform3d& trafo) { switch (type) { case EType::Bed: { return m_bed.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo)); } @@ -41,7 +41,7 @@ std::shared_ptr SceneRaycaster::add_raycaster(EType type, Pi }; } -void SceneRaycaster::remove_raycasters(EType type, PickingId id) +void SceneRaycaster::remove_raycasters(EType type, int id) { std::vector>* raycasters = get_raycasters(type); auto it = raycasters->begin(); @@ -102,7 +102,7 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came HitResult ret; - auto test_raycasters = [&](EType type) { + auto test_raycasters = [this, is_closest, clipping_plane](EType type, const Vec2d& mouse_pos, const Camera& camera, HitResult& ret) { const ClippingPlane* clip_plane = (clipping_plane != nullptr && type == EType::Volume) ? clipping_plane : nullptr; std::vector>* raycasters = get_raycasters(type); HitResult current_hit = { type }; @@ -115,7 +115,6 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came 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; const Matrix3d normal_matrix = (Matrix3d)trafo.matrix().block(0, 0, 3, 3).inverse().transpose(); current_hit.normal = (normal_matrix * current_hit.normal.cast()).normalized().cast(); ret = current_hit; @@ -125,13 +124,13 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came }; if (!m_gizmos.empty()) - test_raycasters(EType::Gizmo); + test_raycasters(EType::Gizmo, mouse_pos, camera, ret); if (!m_gizmos_on_top || !ret.is_valid()) { if (camera.is_looking_downward() && !m_bed.empty()) - test_raycasters(EType::Bed); + test_raycasters(EType::Bed, mouse_pos, camera, ret); if (!m_volumes.empty()) - test_raycasters(EType::Volume); + test_raycasters(EType::Volume, mouse_pos, camera, ret); } if (ret.is_valid()) @@ -146,7 +145,7 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came #if ENABLE_RAYCAST_PICKING_DEBUG void SceneRaycaster::render_hit(const Camera& camera) { - if (!m_last_hit.has_value() || !m_last_hit.value().is_valid()) + if (!m_last_hit.has_value() || !(*m_last_hit).is_valid()) return; GLShaderProgram* shader = wxGetApp().get_shader("flat"); @@ -154,14 +153,14 @@ void SceneRaycaster::render_hit(const Camera& camera) shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - const Transform3d sphere_view_model_matrix = camera.get_view_matrix() * Geometry::translation_transform(m_last_hit.value().position.cast()) * + const Transform3d sphere_view_model_matrix = camera.get_view_matrix() * Geometry::translation_transform((*m_last_hit).position.cast()) * Geometry::scale_transform(4.0 * camera.get_inv_zoom()); shader->set_uniform("view_model_matrix", sphere_view_model_matrix); m_sphere.render(); Eigen::Quaterniond q; Transform3d m = Transform3d::Identity(); - m.matrix().block(0, 0, 3, 3) = q.setFromTwoVectors(Vec3d::UnitZ(), m_last_hit.value().normal.cast()).toRotationMatrix(); + m.matrix().block(0, 0, 3, 3) = q.setFromTwoVectors(Vec3d::UnitZ(), (*m_last_hit).normal.cast()).toRotationMatrix(); const Transform3d line_view_model_matrix = sphere_view_model_matrix * m * Geometry::scale_transform(10.0); shader->set_uniform("view_model_matrix", line_view_model_matrix); @@ -185,28 +184,22 @@ std::vector>* SceneRaycaster::get_raycasters return ret; } -PickingId SceneRaycaster::base_id(EType type) +int SceneRaycaster::base_id(EType type) { switch (type) { - case EType::Bed: { return PickingId(EPickingIdBase::Bed); } - case EType::Volume: { return PickingId(EPickingIdBase::Volume); } - case EType::Gizmo: { return PickingId(EPickingIdBase::Gizmo); } + case EType::Bed: { return int(EIdBase::Bed); } + case EType::Volume: { return int(EIdBase::Volume); } + case EType::Gizmo: { return int(EIdBase::Gizmo); } + default: { break; } }; assert(false); return -1; } -PickingId SceneRaycaster::encode_id(EType type, PickingId id) -{ - return base_id(type) + id; -} - -PickingId SceneRaycaster::decode_id(EType type, PickingId id) -{ - return id - base_id(type); -} +int SceneRaycaster::encode_id(EType type, int id) { return base_id(type) + id; } +int SceneRaycaster::decode_id(EType type, int id) { return id - base_id(type); } } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/SceneRaycaster.hpp b/src/slic3r/GUI/SceneRaycaster.hpp index d0b47dbc75..c4597b6a57 100644 --- a/src/slic3r/GUI/SceneRaycaster.hpp +++ b/src/slic3r/GUI/SceneRaycaster.hpp @@ -3,7 +3,6 @@ #include "MeshUtils.hpp" #include "GLModel.hpp" - #include #include #include @@ -13,21 +12,19 @@ namespace GUI { struct Camera; -using PickingId = int; - class SceneRaycasterItem { - PickingId m_id{ -1 }; + int m_id{ -1 }; bool m_active{ true }; const MeshRaycaster* m_raycaster; Transform3d m_trafo; public: - SceneRaycasterItem(PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) + SceneRaycasterItem(int id, const MeshRaycaster& raycaster, const Transform3d& trafo) : m_id(id), m_raycaster(&raycaster), m_trafo(trafo) {} - PickingId get_id() const { return m_id; } + int get_id() const { return m_id; } bool is_active() const { return m_active; } void set_active(bool active) { m_active = active; } const MeshRaycaster* get_raycaster() const { return m_raycaster; } @@ -46,7 +43,7 @@ public: Gizmo }; - enum class EPickingIdBase + enum class EIdBase { Bed = 0, Volume = 1000, @@ -56,7 +53,7 @@ public: struct HitResult { EType type{ EType::None }; - PickingId raycaster_id{ -1 }; + int raycaster_id{ -1 }; Vec3f position{ Vec3f::Zero() }; Vec3f normal{ Vec3f::Zero() }; @@ -81,11 +78,13 @@ private: public: SceneRaycaster(); - std::shared_ptr add_raycaster(EType type, PickingId picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo); - void remove_raycasters(EType type, PickingId id); + std::shared_ptr add_raycaster(EType type, int picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo); + void remove_raycasters(EType type, int id); 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); @@ -99,11 +98,9 @@ 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); + static int encode_id(EType type, int id); + static int decode_id(EType type, int id); + static int base_id(EType type); }; } // namespace GUI