diff --git a/resources/icons/sla_support_points_reset.png b/resources/icons/sla_support_points_reset.png new file mode 100644 index 000000000..6e051fe95 Binary files /dev/null and b/resources/icons/sla_support_points_reset.png differ diff --git a/resources/icons/sla_support_points_tooltip.png b/resources/icons/sla_support_points_tooltip.png new file mode 100644 index 000000000..1bdfd3440 Binary files /dev/null and b/resources/icons/sla_support_points_tooltip.png differ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ae8feee77..47e750427 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1,3 +1,4 @@ +#include "slic3r/GUI/GLGizmo.hpp" #include "GLCanvas3D.hpp" #include "admesh/stl.h" @@ -7,7 +8,6 @@ #include "slic3r/GUI/GLShader.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/PresetBundle.hpp" -#include "slic3r/GUI/GLGizmo.hpp" #include "libslic3r/ClipperUtils.hpp" #include "libslic3r/PrintConfig.hpp" #include "libslic3r/GCode/PreviewData.hpp" diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 3a6759393..ca52c244a 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -738,7 +738,6 @@ private: wxWindow *m_external_gizmo_widgets_parent; #endif // not ENABLE_IMGUI - void post_event(wxEvent &&event); void viewport_changed(); public: @@ -752,6 +751,7 @@ public: wxGLCanvas* get_wxglcanvas() { return m_canvas; } bool init(bool useVBOs, bool use_legacy_opengl); + void post_event(wxEvent &&event); #if !ENABLE_USE_UNIQUE_GLCONTEXT bool set_current(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index e2d57c8ab..ae2d05542 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -10,7 +10,6 @@ #include #include "libslic3r/Geometry.hpp" -#include #include #include @@ -1627,7 +1626,11 @@ void GLGizmoSlaSupports::set_model_object_ptr(ModelObject* model_object) { m_starting_center = Vec3d::Zero(); m_model_object = model_object; - m_model_object_matrix = model_object->instances.front()->get_matrix(); + + int selected_instance = m_parent.get_selection().get_instance_idx(); + assert(selected_instance < (int)model_object->instances.size()); + + m_instance_matrix = model_object->instances[selected_instance]->get_matrix(); if (is_mesh_update_necessary()) update_mesh(); } @@ -1639,7 +1642,7 @@ void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const ::glEnable(GL_DEPTH_TEST); // the dragged_offset is a vector measuring where was the object moved - // with the gizmo being on. This is reset in set_flattening_data and + // with the gizmo being on. This is reset in set_model_object_ptr and // does not work correctly when there are multiple copies. if (m_starting_center == Vec3d::Zero()) @@ -1653,7 +1656,7 @@ void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const } ::glPushMatrix(); - ::glTranslatef((GLfloat)dragged_offset(0), (GLfloat)dragged_offset(1), (GLfloat)dragged_offset(2)); + //::glTranslatef((GLfloat)dragged_offset(0), (GLfloat)dragged_offset(1), (GLfloat)dragged_offset(2)); render_grabbers(); ::glPopMatrix(); @@ -1675,33 +1678,35 @@ void GLGizmoSlaSupports::on_render_for_picking(const GLCanvas3D::Selection& sele void GLGizmoSlaSupports::render_grabbers(bool picking) const { - for (int i = 0; i < (int)m_grabbers.size(); ++i) - { - if (!m_grabbers[i].enabled) - continue; + for (const ModelInstance* inst : m_model_object->instances) { + for (int i = 0; i < (int)m_grabbers.size(); ++i) + { + if (!m_grabbers[i].enabled) + continue; - float render_color[3]; - if (!picking && m_hover_id == i) { - render_color[0] = 1.0f - m_grabbers[i].color[0]; - render_color[1] = 1.0f - m_grabbers[i].color[1]; - render_color[2] = 1.0f - m_grabbers[i].color[2]; + float render_color[3]; + if (!picking && m_hover_id == i) { + render_color[0] = 1.0f - m_grabbers[i].color[0]; + render_color[1] = 1.0f - m_grabbers[i].color[1]; + render_color[2] = 1.0f - m_grabbers[i].color[2]; + } + else + ::memcpy((void*)render_color, (const void*)m_grabbers[i].color, 3 * sizeof(float)); + if (!picking) + ::glEnable(GL_LIGHTING); + ::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]); + ::glPushMatrix(); + Vec3d center = inst->get_matrix() * m_grabbers[i].center; + ::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2)); + GLUquadricObj *quadric; + quadric = ::gluNewQuadric(); + ::gluQuadricDrawStyle(quadric, GLU_FILL ); + ::gluSphere( quadric , 0.75f, 36 , 18 ); + ::gluDeleteQuadric(quadric); + ::glPopMatrix(); + if (!picking) + ::glDisable(GL_LIGHTING); } - else - ::memcpy((void*)render_color, (const void*)m_grabbers[i].color, 3 * sizeof(float)); - if (!picking) - ::glEnable(GL_LIGHTING); - ::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]); - ::glPushMatrix(); - Vec3d center = m_model_object_matrix * m_grabbers[i].center; - ::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2)); - GLUquadricObj *quadric; - quadric = ::gluNewQuadric(); - ::gluQuadricDrawStyle(quadric, GLU_FILL ); - ::gluSphere( quadric , 0.75f, 36 , 18 ); - ::gluDeleteQuadric(quadric); - ::glPopMatrix(); - if (!picking) - ::glDisable(GL_LIGHTING); } } @@ -1710,7 +1715,7 @@ bool GLGizmoSlaSupports::is_mesh_update_necessary() const if (m_state != On || !m_model_object || m_model_object->instances.empty()) return false; - if ((m_model_object->instances.front()->get_matrix() * m_source_data.matrix.inverse() * Vec3d(1., 1., 1.) - Vec3d(1., 1., 1.)).norm() > 0.001) + if ((m_instance_matrix * m_source_data.matrix.inverse() * Vec3d(1., 1., 1.) - Vec3d(1., 1., 1.)).norm() > 0.001) return true; // following should detect direct mesh changes (can be removed after the mesh is made completely immutable): @@ -1726,7 +1731,7 @@ void GLGizmoSlaSupports::update_mesh() { Eigen::MatrixXf& V = m_V; Eigen::MatrixXi& F = m_F; - TriangleMesh mesh(m_model_object->mesh()); + TriangleMesh mesh = m_model_object->mesh(); const stl_file& stl = mesh.stl; V.resize(3 * stl.stats.number_of_facets, 3); F.resize(stl.stats.number_of_facets, 3); @@ -1739,15 +1744,19 @@ void GLGizmoSlaSupports::update_mesh() F(i, 1) = 3*i+1; F(i, 2) = 3*i+2; } - m_source_data.matrix = m_model_object->instances.front()->get_matrix(); - const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex(); - m_source_data.mesh_first_point = Vec3d((double)first_vertex[0], (double)first_vertex[1], (double)first_vertex[2]); + + m_AABB = igl::AABB(); + m_AABB.init(m_V, m_F); + + m_source_data.matrix = m_instance_matrix; + // we'll now reload Grabbers (selection might have changed): m_grabbers.clear(); for (const Vec3f& point : m_model_object->sla_support_points) { m_grabbers.push_back(Grabber()); m_grabbers.back().center = point.cast(); } + m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) @@ -1763,24 +1772,21 @@ Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) Eigen::Matrix projection_matrix; ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data()); - int fid = 0; - Eigen::Vector3f bc(0, 0, 0); - if (!igl::unproject_onto_mesh(Vec2f(mouse_pos(0), viewport(3)-mouse_pos(1)), modelview_matrix.cast(), projection_matrix.cast(), viewport.cast(), m_V, m_F, fid, bc)) - /*if (!igl::embree::unproject_onto_mesh(Vec2f(mouse_pos(0), viewport(3)-mouse_pos(1)), - m_F, - modelview_matrix.cast(), - projection_matrix.cast(), - viewport.cast(), - m_intersector, - fid, - bc))*/ - throw "unable to unproject_onto_mesh"; + Vec3d point1; + Vec3d point2; + ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2)); + ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2)); - const Vec3f& a = m_V.row(m_F(fid, 0)); - const Vec3f& b = m_V.row(m_F(fid, 1)); - const Vec3f& c = m_V.row(m_F(fid, 2)); - Vec3f point = bc(0)*a + bc(1)*b + bc(2)*c; - return m_model_object->instances.front()->get_matrix().inverse().cast() * point; + igl::Hit hit; + + if (!m_AABB.intersect_ray(m_V, m_F, point1.cast(), (point2-point1).cast(), hit)) + throw std::invalid_argument("unproject_on_mesh(): No intersection found."); + + int fid = hit.id; + Vec3f bc(1-hit.u-hit.v, hit.u, hit.v); + Vec3f point = bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2)); + + return m_instance_matrix.inverse().cast() * point; } void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position) @@ -1788,14 +1794,17 @@ void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position) Vec3f new_pos; try { new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new grabber in that case - m_grabbers.push_back(Grabber()); - m_grabbers.back().center = new_pos.cast(); - m_model_object->sla_support_points.push_back(new_pos); - - // This should trigger the support generation - // wxGetApp().plater()->reslice(); } - catch (...) {} + catch (...) { return; } + + m_grabbers.push_back(Grabber()); + m_grabbers.back().center = new_pos.cast(); + m_model_object->sla_support_points.push_back(new_pos); + + // This should trigger the support generation + // wxGetApp().plater()->reslice(); + + m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } void GLGizmoSlaSupports::delete_current_grabber(bool delete_all) @@ -1816,6 +1825,8 @@ void GLGizmoSlaSupports::delete_current_grabber(bool delete_all) // This should trigger the support generation // wxGetApp().plater()->reslice(); } + + m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } void GLGizmoSlaSupports::on_update(const UpdateData& data) @@ -1824,20 +1835,21 @@ void GLGizmoSlaSupports::on_update(const UpdateData& data) Vec3f new_pos; try { new_pos = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1))); - m_grabbers[m_hover_id].center = new_pos.cast(); - m_model_object->sla_support_points[m_hover_id] = new_pos; } - catch (...) {} + catch (...) { return; } + m_grabbers[m_hover_id].center = new_pos.cast(); + m_model_object->sla_support_points[m_hover_id] = new_pos; + m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } } void GLGizmoSlaSupports::render_tooltip_texture() const { if (m_tooltip_texture.get_id() == 0) - if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/variable_layer_height_tooltip.png", false)) + if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/sla_support_points_tooltip.png", false)) return; if (m_reset_texture.get_id() == 0) - if (!m_reset_texture.load_from_file(resources_dir() + "/icons/variable_layer_height_reset.png", false)) + if (!m_reset_texture.load_from_file(resources_dir() + "/icons/sla_support_points_reset.png", false)) return; float zoom = m_parent.get_camera_zoom(); @@ -1863,7 +1875,8 @@ void GLGizmoSlaSupports::render_tooltip_texture() const { bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const { - return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA); + return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) + && selection.is_from_single_instance(); } bool GLGizmoSlaSupports::on_is_selectable() const diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 64bd71876..6ce22f395 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -1,6 +1,8 @@ #ifndef slic3r_GLGizmo_hpp_ #define slic3r_GLGizmo_hpp_ +#include + #include "../../slic3r/GUI/GLTexture.hpp" #include "../../slic3r/GUI/GLCanvas3D.hpp" #include "../../libslic3r/Point.hpp" @@ -449,11 +451,13 @@ class GLGizmoSlaSupports : public GLGizmoBase { private: ModelObject* m_model_object = nullptr; - Transform3d m_model_object_matrix; + Transform3d m_instance_matrix; Vec3f unproject_on_mesh(const Vec2d& mouse_pos); Eigen::MatrixXf m_V; // vertices Eigen::MatrixXi m_F; // facets indices + igl::AABB m_AABB; + struct SourceDataSummary { BoundingBoxf3 bounding_box; Transform3d matrix;