diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 41361eaa9..e90f76fc4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -120,6 +120,10 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix(); + bool is_left_handed = trafo_matrix.matrix().determinant() < 0.; + if (is_left_handed) + glsafe(::glFrontFace(GL_CW)); + glsafe(::glPushMatrix()); glsafe(::glMultMatrixd(trafo_matrix.data())); @@ -130,6 +134,8 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const iva.render(); } glsafe(::glPopMatrix()); + if (is_left_handed) + glsafe(::glFrontFace(GL_CCW)); } if (clipping_plane_active) glsafe(::glDisable(GL_CLIP_PLANE0)); @@ -205,7 +211,6 @@ void GLGizmoFdmSupports::update_from_model_object() if (mv->is_model_part()) ++num_of_volumes; m_selected_facets.resize(num_of_volumes); - m_neighbors.resize(num_of_volumes); m_ivas.clear(); m_ivas.resize(num_of_volumes); @@ -235,17 +240,6 @@ void GLGizmoFdmSupports::update_from_model_object() } update_vertex_buffers(mesh, volume_id, FacetSupportType::ENFORCER); update_vertex_buffers(mesh, volume_id, FacetSupportType::BLOCKER); - - m_neighbors[volume_id].resize(3 * mesh->its.indices.size()); - - // Prepare vector of vertex_index - facet_index pairs to quickly find adjacent facets - for (size_t i=0; iits.indices.size(); ++i) { - const stl_triangle_vertex_indices& ind = mesh->its.indices[i]; - m_neighbors[volume_id][3*i] = std::make_pair(ind(0), i); - m_neighbors[volume_id][3*i+1] = std::make_pair(ind(1), i); - m_neighbors[volume_id][3*i+2] = std::make_pair(ind(2), i); - } - std::sort(m_neighbors[volume_id].begin(), m_neighbors[volume_id].end()); } } @@ -267,11 +261,6 @@ bool GLGizmoFdmSupports::is_mesh_point_clipped(const Vec3d& point) const } -bool operator<(const GLGizmoFdmSupports::NeighborData& a, const GLGizmoFdmSupports::NeighborData& b) { - return a.first < b.first; -} - - // Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event. // The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is // aware that the event was reacted to and stops trying to make different sense of it. If the gizmo @@ -325,7 +314,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous const Transform3d& instance_trafo = mi->get_transformation().get_matrix(); std::vector>> hit_positions_and_facet_ids; - bool some_mesh_was_hit = false; + bool clipped_mesh_was_hit = false; Vec3f normal = Vec3f::Zero(); Vec3f hit = Vec3f::Zero(); @@ -360,7 +349,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous { // In case this hit is clipped, skip it. if (is_mesh_point_clipped(hit.cast())) { - some_mesh_was_hit = true; + clipped_mesh_was_hit = true; continue; } @@ -374,124 +363,119 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous } } } - // We now know where the ray hit, let's save it and cast another ray - if (closest_hit_mesh_id != size_t(-1)) // only if there is at least one hit - some_mesh_was_hit = true; - if (some_mesh_was_hit) { - // Now propagate the hits - mesh_id = -1; - const TriangleMesh* mesh = nullptr; - for (const ModelVolume* mv : mo->volumes) { - if (! mv->is_model_part()) - continue; - ++mesh_id; - if (mesh_id == closest_hit_mesh_id) { - mesh = &mv->mesh(); - break; - } + if (closest_hit_mesh_id == -1) { + // In case we have no valid hit, we can return. The event will + // be stopped in following two cases: + // 1. clicking the clipping plane + // 2. dragging while painting (to prevent scene rotations and moving the object) + return clipped_mesh_was_hit + || (action == SLAGizmoEventType::Dragging && m_button_down != Button::None); + } + + // Now propagate the hits + mesh_id = -1; + const TriangleMesh* mesh = nullptr; + for (const ModelVolume* mv : mo->volumes) { + if (! mv->is_model_part()) + continue; + ++mesh_id; + if (mesh_id == closest_hit_mesh_id) { + mesh = &mv->mesh(); + break; } + } - bool update_both = false; + bool update_both = false; - const Transform3d& trafo_matrix = trafo_matrices[mesh_id]; + const Transform3d& trafo_matrix = trafo_matrices[mesh_id]; - // Calculate how far can a point be from the line (in mesh coords). - // FIXME: The scaling of the mesh can be non-uniform. - const Vec3d sf = Geometry::Transformation(trafo_matrix).get_scaling_factor(); - const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.; - const float limit = pow(m_cursor_radius/avg_scaling , 2.f); + // Calculate how far can a point be from the line (in mesh coords). + // FIXME: The scaling of the mesh can be non-uniform. + const Vec3d sf = Geometry::Transformation(trafo_matrix).get_scaling_factor(); + const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.; + const float limit = pow(m_cursor_radius/avg_scaling , 2.f); - const std::pair& hit_and_facet = { closest_hit, closest_facet }; + const std::pair& hit_and_facet = { closest_hit, closest_facet }; - const std::vector& neighbors = m_neighbors[mesh_id]; + // Calculate direction from camera to the hit (in mesh coords): + Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast() - hit_and_facet.first).normalized(); - // Calculate direction from camera to the hit (in mesh coords): - Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast() - hit_and_facet.first).normalized(); + // A lambda to calculate distance from the centerline: + auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f& point) -> float { + Vec3f diff = hit_and_facet.first - point; + return (diff - diff.dot(dir) * dir).squaredNorm(); + }; - // A lambda to calculate distance from the centerline: - auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f& point) -> float { - Vec3f diff = hit_and_facet.first - point; - return (diff - diff.dot(dir) * dir).squaredNorm(); - }; - - // A lambda to determine whether this facet is potentionally visible (still can be obscured) - auto faces_camera = [&dir, &mesh](const size_t& facet) -> bool { - return (mesh->stl.facet_start[facet].normal.dot(dir) > 0.); - }; - // Now start with the facet the pointer points to and check all adjacent facets. neighbors vector stores - // pairs of vertex_idx - facet_idx and is sorted with respect to the former. Neighboring facet index can be - // quickly found by finding a vertex in the list and read the respective facet ids. - std::vector facets_to_select{hit_and_facet.second}; - NeighborData vertex = std::make_pair(0, 0); - std::vector visited(m_selected_facets[mesh_id].size(), false); // keep track of facets we already processed - size_t facet_idx = 0; // index into facets_to_select - auto it = neighbors.end(); - while (facet_idx < facets_to_select.size()) { - size_t facet = facets_to_select[facet_idx]; - if (! visited[facet]) { - // check all three vertices and in case they're close enough, find the remaining facets - // and add them to the list to be proccessed later - for (size_t i=0; i<3; ++i) { - vertex.first = mesh->its.indices[facet](i); // vertex index - float dist = squared_distance_from_line(mesh->its.vertices[vertex.first]); - if (dist < limit) { - it = std::lower_bound(neighbors.begin(), neighbors.end(), vertex); - while (it != neighbors.end() && it->first == vertex.first) { - if (it->second != facet && faces_camera(it->second)) - facets_to_select.push_back(it->second); - ++it; - } + // A lambda to determine whether this facet is potentionally visible (still can be obscured) + auto faces_camera = [&dir, &mesh](const size_t& facet) -> bool { + return (mesh->stl.facet_start[facet].normal.dot(dir) > 0.); + }; + // Now start with the facet the pointer points to and check all adjacent facets. + std::vector facets_to_select{hit_and_facet.second}; + std::vector visited(m_selected_facets[mesh_id].size(), false); // keep track of facets we already processed + size_t facet_idx = 0; // index into facets_to_select + while (facet_idx < facets_to_select.size()) { + size_t facet = facets_to_select[facet_idx]; + if (! visited[facet]) { + // check all three vertices and in case they're close enough, + // add neighboring facets to be proccessed later + for (size_t i=0; i<3; ++i) { + float dist = squared_distance_from_line( + mesh->its.vertices[mesh->its.indices[facet](i)]); + if (dist < limit) { + for (int n=0; n<3; ++n) { + if (faces_camera(mesh->stl.neighbors_start[facet].neighbor[n])) + facets_to_select.push_back(mesh->stl.neighbors_start[facet].neighbor[n]); } } - visited[facet] = true; } - ++facet_idx; + visited[facet] = true; } - - std::vector new_facets; - new_facets.reserve(facets_to_select.size()); - - // Now just select all facets that passed and remember which - // ones have really changed state. - for (size_t next_facet : facets_to_select) { - FacetSupportType& facet = m_selected_facets[mesh_id][next_facet]; - - if (facet != new_state) { - if (facet != FacetSupportType::NONE) { - // this triangle is currently in the other VBA. - // Both VBAs need to be refreshed. - update_both = true; - } - facet = new_state; - new_facets.push_back(next_facet); - } - } - - if (! new_facets.empty()) { - if (new_state != FacetSupportType::NONE) { - // append triangles into the respective VBA - update_vertex_buffers(mesh, mesh_id, new_state, &new_facets); - if (update_both) { - auto other = new_state == FacetSupportType::ENFORCER - ? FacetSupportType::BLOCKER - : FacetSupportType::ENFORCER; - update_vertex_buffers(mesh, mesh_id, other); // regenerate the other VBA - } - } - else { - update_vertex_buffers(mesh, mesh_id, FacetSupportType::ENFORCER); - update_vertex_buffers(mesh, mesh_id, FacetSupportType::BLOCKER); - } - } - - - if (m_button_down == Button::None) - m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right); - return true; + ++facet_idx; } - if (action == SLAGizmoEventType::Dragging && m_button_down != Button::None) - return true; + + std::vector new_facets; + new_facets.reserve(facets_to_select.size()); + + // Now just select all facets that passed and remember which + // ones have really changed state. + for (size_t next_facet : facets_to_select) { + FacetSupportType& facet = m_selected_facets[mesh_id][next_facet]; + + if (facet != new_state) { + if (facet != FacetSupportType::NONE) { + // this triangle is currently in the other VBA. + // Both VBAs need to be refreshed. + update_both = true; + } + facet = new_state; + new_facets.push_back(next_facet); + } + } + + if (! new_facets.empty()) { + if (new_state != FacetSupportType::NONE) { + // append triangles into the respective VBA + update_vertex_buffers(mesh, mesh_id, new_state, &new_facets); + if (update_both) { + auto other = new_state == FacetSupportType::ENFORCER + ? FacetSupportType::BLOCKER + : FacetSupportType::ENFORCER; + update_vertex_buffers(mesh, mesh_id, other); // regenerate the other VBA + } + } + else { + update_vertex_buffers(mesh, mesh_id, FacetSupportType::ENFORCER); + update_vertex_buffers(mesh, mesh_id, FacetSupportType::BLOCKER); + } + } + + + if (m_button_down == Button::None) + m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right); + + return true; } if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp) @@ -809,7 +793,6 @@ void GLGizmoFdmSupports::on_set_state() } m_old_mo_id = -1; m_ivas.clear(); - m_neighbors.clear(); m_selected_facets.clear(); } m_old_state = m_state; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index e7f3a2063..f481afc37 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -49,7 +49,6 @@ public: ~GLGizmoFdmSupports() override; void set_fdm_support_data(ModelObject* model_object, const Selection& selection); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); - using NeighborData = std::pair; private: @@ -86,8 +85,6 @@ private: Button m_button_down = Button::None; EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state) - std::vector> m_neighbors; // pairs of vertex_index - facet_index for each mesh - protected: void on_set_state() override; void on_start_dragging() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 7f33916cd..3f2c0ea46 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -1,7 +1,6 @@ // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. #include "GLGizmoFlatten.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" -#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include @@ -80,12 +79,7 @@ void GLGizmoFlatten::on_render() const else glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.5f)); - ::glBegin(GL_POLYGON); - for (const Vec3d& vertex : m_planes[i].vertices) - { - ::glVertex3dv(vertex.data()); - } - glsafe(::glEnd()); + m_planes[i].vbo.render(); } glsafe(::glPopMatrix()); } @@ -112,12 +106,7 @@ void GLGizmoFlatten::on_render_for_picking() const for (int i = 0; i < (int)m_planes.size(); ++i) { glsafe(::glColor4fv(picking_color_component(i).data())); - ::glBegin(GL_POLYGON); - for (const Vec3d& vertex : m_planes[i].vertices) - { - ::glVertex3dv(vertex.data()); - } - glsafe(::glEnd()); + m_planes[i].vbo.render(); } glsafe(::glPopMatrix()); } @@ -181,7 +170,7 @@ void GLGizmoFlatten::update_planes() if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) { stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex; for (int j=0; j<3; ++j) - m_planes.back().vertices.emplace_back((double)first_vertex[j](0), (double)first_vertex[j](1), (double)first_vertex[j](2)); + m_planes.back().vertices.emplace_back(first_vertex[j].cast()); facet_visited[facet_idx] = true; for (int j = 0; j < 3; ++ j) { @@ -193,15 +182,16 @@ void GLGizmoFlatten::update_planes() } m_planes.back().normal = normal_ptr->cast(); + Pointf3s& verts = m_planes.back().vertices; // Now we'll transform all the points into world coordinates, so that the areas, angles and distances // make real sense. - m_planes.back().vertices = transform(m_planes.back().vertices, inst_matrix); + verts = transform(verts, inst_matrix); // if this is a just a very small triangle, remove it to speed up further calculations (it would be rejected later anyway): - if (m_planes.back().vertices.size() == 3 && - ((m_planes.back().vertices[0] - m_planes.back().vertices[1]).norm() < minimal_side - || (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < minimal_side - || (m_planes.back().vertices[1] - m_planes.back().vertices[2]).norm() < minimal_side)) + if (verts.size() == 3 && + ((verts[0] - verts[1]).norm() < minimal_side + || (verts[0] - verts[2]).norm() < minimal_side + || (verts[1] - verts[2]).norm() < minimal_side)) m_planes.pop_back(); } @@ -246,7 +236,7 @@ void GLGizmoFlatten::update_planes() discard = true; else { // We also check the inner angles and discard polygons with angles smaller than the following threshold - const double angle_threshold = ::cos(10.0 * (double)PI / 180.0); + constexpr double angle_threshold = ::cos(10.0 * (double)PI / 180.0); for (unsigned int i = 0; i < polygon.size(); ++i) { const Vec3d& prec = polygon[(i == 0) ? polygon.size() - 1 : i - 1]; @@ -334,6 +324,21 @@ void GLGizmoFlatten::update_planes() m_first_instance_mirror = mo->instances.front()->get_mirror(); m_old_model_object = mo; + // And finally create respective VBOs. The polygon is convex with + // the vertices in order, so triangulation is trivial. + for (auto& plane : m_planes) { + plane.vbo.reserve(plane.vertices.size()); + for (const auto& vert : plane.vertices) + plane.vbo.push_geometry(vert, plane.normal); + for (size_t i=1; i vertices; + std::vector vertices; // should be in fact local in update_planes() + GLIndexedVertexArray vbo; Vec3d normal; float area; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 261738d44..712311e81 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -898,6 +898,7 @@ void GLGizmoSlaSupports::on_set_state() // Set default head diameter from config. const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; m_new_point_head_diameter = static_cast(cfg.option("support_head_front_diameter"))->value; + m_c->instances_hider()->show_supports(true); } if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off bool will_ask = mo && m_editing_mode && unsaved_changes(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 32a6de42b..e35750fa0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -342,15 +342,11 @@ void ObjectClipper::render_cut() const clipper->set_plane(*m_clp); clipper->set_transformation(trafo); - if (! clipper->get_triangles().empty()) { - ::glPushMatrix(); - ::glColor3f(1.0f, 0.37f, 0.0f); - ::glBegin(GL_TRIANGLES); - for (const Vec3f& point : clipper->get_triangles()) - ::glVertex3f(point(0), point(1), point(2)); - ::glEnd(); - ::glPopMatrix(); - } + ::glPushMatrix(); + ::glColor3f(1.0f, 0.37f, 0.0f); + clipper->render_cut(); + ::glPopMatrix(); + ++clipper_id; } } @@ -457,15 +453,10 @@ void SupportsClipper::render_cut() const m_clipper->set_plane(*ocl->get_clipping_plane()); m_clipper->set_transformation(supports_trafo); - if (! m_clipper->get_triangles().empty()) { - ::glPushMatrix(); - ::glColor3f(1.0f, 0.f, 0.37f); - ::glBegin(GL_TRIANGLES); - for (const Vec3f& point : m_clipper->get_triangles()) - ::glVertex3f(point(0), point(1), point(2)); - ::glEnd(); - ::glPopMatrix(); - } + ::glPushMatrix(); + ::glColor3f(1.0f, 0.f, 0.37f); + m_clipper->render_cut(); + ::glPopMatrix(); } diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index 18526d8ce..413eedda5 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -27,7 +27,6 @@ void MeshClipper::set_mesh(const TriangleMesh& mesh) m_mesh = &mesh; m_triangles_valid = false; m_triangles2d.resize(0); - m_triangles3d.resize(0); m_tms.reset(nullptr); } } @@ -40,18 +39,17 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo) m_trafo = trafo; m_triangles_valid = false; m_triangles2d.resize(0); - m_triangles3d.resize(0); } } -const std::vector& MeshClipper::get_triangles() +void MeshClipper::render_cut() { if (! m_triangles_valid) recalculate_triangles(); - return m_triangles3d; + m_vertex_array.render(); } @@ -67,29 +65,35 @@ void MeshClipper::recalculate_triangles() const Vec3f& scaling = m_trafo.get_scaling_factor().cast(); // Calculate clipping plane normal in mesh coordinates. Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_plane.get_normal().cast(); - Vec3f up (up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2)); + Vec3d up (up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2)); // Calculate distance from mesh origin to the clipping plane (in mesh coordinates). float height_mesh = m_plane.distance(m_trafo.get_offset()) * (up_noscale.norm()/up.norm()); // Now do the cutting std::vector list_of_expolys; - m_tms->set_up_direction(up); + m_tms->set_up_direction(up.cast()); m_tms->slice(std::vector{height_mesh}, SlicingMode::Regular, 0.f, &list_of_expolys, [](){}); m_triangles2d = triangulate_expolygons_2f(list_of_expolys[0], m_trafo.get_matrix().matrix().determinant() < 0.); // Rotate the cut into world coords: - Eigen::Quaternionf q; - q.setFromTwoVectors(Vec3f::UnitZ(), up); - Transform3f tr = Transform3f::Identity(); + Eigen::Quaterniond q; + q.setFromTwoVectors(Vec3d::UnitZ(), up); + Transform3d tr = Transform3d::Identity(); tr.rotate(q); - tr = m_trafo.get_matrix().cast() * tr; + tr = m_trafo.get_matrix() * tr; - m_triangles3d.clear(); - m_triangles3d.reserve(m_triangles2d.size()); - for (const Vec2f& pt : m_triangles2d) { - m_triangles3d.push_back(Vec3f(pt(0), pt(1), height_mesh+0.001f)); - m_triangles3d.back() = tr * m_triangles3d.back(); - } + // to avoid z-fighting + height_mesh += 0.001f; + + m_vertex_array.release_geometry(); + for (auto it=m_triangles2d.cbegin(); it != m_triangles2d.cend(); it=it+3) { + m_vertex_array.push_geometry(tr * Vec3d((*(it+0))(0), (*(it+0))(1), height_mesh), up); + m_vertex_array.push_geometry(tr * Vec3d((*(it+1))(0), (*(it+1))(1), height_mesh), up); + m_vertex_array.push_geometry(tr * Vec3d((*(it+2))(0), (*(it+2))(1), height_mesh), up); + size_t idx = it - m_triangles2d.cbegin(); + m_vertex_array.push_triangle(idx, idx+1, idx+2); + } + m_vertex_array.finalize_geometry(true); m_triangles_valid = true; } diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index 8e321730c..3cb9b58f2 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -6,7 +6,7 @@ #include "libslic3r/SLA/EigenMesh3D.hpp" #include "admesh/stl.h" - +#include "slic3r/GUI/3DScene.hpp" #include @@ -82,9 +82,9 @@ public: // into world coordinates. void set_transformation(const Geometry::Transformation& trafo); - // Return the triangulated cut. The points are returned directly - // in world coordinates. - const std::vector& get_triangles(); + // Render the triangulated cut. Transformation matrices should + // be set in world coords. + void render_cut(); private: void recalculate_triangles(); @@ -93,7 +93,7 @@ private: const TriangleMesh* m_mesh = nullptr; ClippingPlane m_plane; std::vector m_triangles2d; - std::vector m_triangles3d; + GLIndexedVertexArray m_vertex_array; bool m_triangles_valid = false; std::unique_ptr m_tms; };