From 0b68a3ac727e7dc92cd42641a6022613bef3ea05 Mon Sep 17 00:00:00 2001 From: "zhou.xu" Date: Wed, 8 Nov 2023 12:04:50 +0800 Subject: [PATCH] FIX:fix GLmodel deconstruction causing section not to be rendered Jira: STUDIO-5156 Change-Id: Ibb2f459920989ee54f7b827352dc8893424b4de6 --- src/slic3r/GUI/MeshUtils.cpp | 92 +++++++++++++++++++++++------------- src/slic3r/GUI/MeshUtils.hpp | 5 +- 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index 9336e27a6..751bfd664 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -18,9 +18,14 @@ namespace Slic3r { namespace GUI { +MeshClipper::~MeshClipper() { + reset(); +} + void MeshClipper::set_behaviour(bool fill_cut, double contour_width) { - if (fill_cut != m_fill_cut || !is_approx(contour_width, m_contour_width)) m_result.reset(); + if (fill_cut != m_fill_cut || !is_approx(contour_width, m_contour_width)) + reset(); m_fill_cut = fill_cut; m_contour_width = contour_width; } @@ -29,7 +34,7 @@ void MeshClipper::set_plane(const ClippingPlane &plane) { if (m_plane != plane) { m_plane = plane; - m_result.reset(); + reset(); } } @@ -37,7 +42,7 @@ void MeshClipper::set_limiting_plane(const ClippingPlane& plane) { if (m_limiting_plane != plane) { m_limiting_plane = plane; - m_result.reset(); + reset(); } } @@ -45,7 +50,7 @@ void MeshClipper::set_mesh(const TriangleMesh& mesh) { if (m_mesh != &mesh) { m_mesh = &mesh; - m_result.reset(); + reset(); } } @@ -53,7 +58,7 @@ void MeshClipper::set_negative_mesh(const TriangleMesh& mesh) { if (m_negative_mesh != &mesh) { m_negative_mesh = &mesh; - m_result.reset(); + reset(); } } @@ -63,7 +68,7 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo) { if (! m_trafo.get_matrix().isApprox(trafo.get_matrix())) { m_trafo = trafo; - m_result.reset(); + reset(); } } @@ -81,10 +86,10 @@ void MeshClipper::render_cut(const ColorRGBA &color, const std::vector * shader->set_uniform("projection_matrix", camera.get_projection_matrix()); for (size_t i = 0; i < m_result->cut_islands.size(); ++i) { if (ignore_idxs && std::binary_search(ignore_idxs->begin(), ignore_idxs->end(), i)) continue; - CutIsland &isl = m_result->cut_islands[i]; + auto isl = m_result->cut_islands[i]; ColorRGBA gray{0.5f, 0.5f, 0.5f, 1.f}; - isl.model.set_color(-1, isl.disabled ? gray : color); - isl.model.render(); + isl->model.set_color(-1, isl->disabled ? gray : color); + isl->model.render(); } shader->stop_using(); } @@ -107,15 +112,15 @@ void MeshClipper::render_contour(const ColorRGBA &color, const std::vectorset_uniform("projection_matrix", camera.get_projection_matrix()); for (size_t i = 0; i < m_result->cut_islands.size(); ++i) { if (ignore_idxs && std::binary_search(ignore_idxs->begin(), ignore_idxs->end(), i)) continue; - CutIsland &isl = m_result->cut_islands[i]; + auto isl = m_result->cut_islands[i]; ColorRGBA red{1.0f, 0.f, 0.f, 1.f}; - isl.model_expanded.set_color(-1, isl.disabled ? red : color); - isl.model_expanded.render(); + isl->model_expanded.set_color(-1, isl->disabled ? red : color); + isl->model_expanded.render(); } shader->stop_using(); } - if (curr_shader != nullptr) + if (curr_shader != nullptr) curr_shader->start_using(); } @@ -127,8 +132,8 @@ int MeshClipper::is_projection_inside_cut(const Vec3d &point_in) const Point pt_2d = Point::new_scale(Vec2d(point.x(), point.y())); for (int i = 0; i < int(m_result->cut_islands.size()); ++i) { - const CutIsland &isl = m_result->cut_islands[i]; - if (isl.expoly_bb.contains(pt_2d) && isl.expoly.contains(pt_2d)) + auto isl = m_result->cut_islands[i]; + if (isl->expoly_bb.contains(pt_2d) && isl->expoly.contains(pt_2d)) return i; // TODO: handle intersecting contours } return -1; @@ -136,7 +141,7 @@ int MeshClipper::is_projection_inside_cut(const Vec3d &point_in) const bool MeshClipper::has_valid_contour() const { - return m_result && std::any_of(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](const CutIsland &isl) { return !isl.expoly.empty(); }); + return m_result && std::any_of(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](CutIsland *isl) { return isl &&!isl->expoly.empty(); }); } std::vector MeshClipper::point_per_contour() const { @@ -145,7 +150,7 @@ std::vector MeshClipper::point_per_contour() const { return out; } assert(m_result); - for (const CutIsland &isl : m_result->cut_islands) { + for (auto isl : m_result->cut_islands) { assert(isl.expoly.contour.size() > 2); // Now return a point lying inside the contour but not in a hole. // We do this by taking a point lying close to the edge, repeating @@ -154,27 +159,27 @@ std::vector MeshClipper::point_per_contour() const { bool done = false; Vec2d p; size_t i = 1; - while (i < isl.expoly.contour.size()) { - const Vec2d &a = unscale(isl.expoly.contour.points[i - 1]); - const Vec2d &b = unscale(isl.expoly.contour.points[i]); + while (i < isl->expoly.contour.size()) { + const Vec2d &a = unscale(isl->expoly.contour.points[i - 1]); + const Vec2d &b = unscale(isl->expoly.contour.points[i]); Vec2d n = (b - a).normalized(); std::swap(n.x(), n.y()); n.x() = -1 * n.x(); double f = 10.; while (f > 0.05) { p = (0.5 * (b + a)) + f * n; - if (isl.expoly.contains(Point::new_scale(p))) { + if (isl->expoly.contains(Point::new_scale(p))) { done = true; break; } f = f / 10.; } if (done) break; - i += std::max(size_t(2), isl.expoly.contour.size() / 5); + i += std::max(size_t(2), isl->expoly.contour.size() / 5); } // If the above failed, just return the centroid, regardless of whether // it is inside the contour or in a hole (we must return something). - Vec2d c = done ? p : unscale(isl.expoly.contour.centroid()); + Vec2d c = done ? p : unscale(isl->expoly.contour.centroid()); out.emplace_back(m_result->trafo * Vec3d(c.x(), c.y(), 0.)); } return out; @@ -268,12 +273,15 @@ void MeshClipper::recalculate_triangles() std::vector triangles2d; + m_result->cut_islands.resize(expolys.size()); + int isl_index = 0; for (const ExPolygon &exp : expolys) { triangles2d.clear(); - - m_result->cut_islands.push_back(CutIsland()); - CutIsland &isl = m_result->cut_islands.back(); - + if (!m_result->cut_islands[isl_index]) { + m_result->cut_islands[isl_index] = new CutIsland(); + } + CutIsland* isl = m_result->cut_islands[isl_index]; + isl_index++; if (m_fill_cut) { triangles2d = triangulate_expolygon_2f(exp, m_trafo.get_matrix().matrix().determinant() < 0.); GLModel::InitializationData init_data; // GLModel::Geometry init_data; @@ -309,7 +317,10 @@ void MeshClipper::recalculate_triangles() init_data.entities.back().indices.push_back((unsigned int) idx + 2); } - if (init_data.entities.back().indices.size() != 0) isl.model.init_from(std::move(init_data)); + if (init_data.entities.back().indices.size() != 0) { + isl->model.reset(); + isl->model.init_from(std::move(init_data)); + } } if (m_contour_width != 0. && !exp.contour.empty()) { @@ -373,23 +384,36 @@ void MeshClipper::recalculate_triangles() init_data.entities.back().indices.push_back((unsigned int) idx + 2); } - if (init_data.entities.back().indices.size() != 0) isl.model_expanded.init_from(std::move(init_data)); + if (init_data.entities.back().indices.size() != 0) { + isl->model_expanded.reset(); + isl->model_expanded.init_from(std::move(init_data)); + } } - isl.expoly = std::move(exp); - isl.expoly_bb = get_extents(isl.expoly); + isl->expoly = std::move(exp); + isl->expoly_bb = get_extents(isl->expoly); - Point centroid_scaled = isl.expoly.contour.centroid(); + Point centroid_scaled = isl->expoly.contour.centroid(); Vec3d centroid_world = m_result->trafo * Vec3d(unscale(centroid_scaled).x(), unscale(centroid_scaled).y(), 0.); - isl.hash = isl.expoly.contour.size() + size_t(std::abs(100. * centroid_world.x())) + size_t(std::abs(100. * centroid_world.y())) + + isl->hash = isl->expoly.contour.size() + size_t(std::abs(100. * centroid_world.x())) + size_t(std::abs(100. * centroid_world.y())) + size_t(std::abs(100. * centroid_world.z())); } // Now sort the islands so they are in defined order. This is a hack needed by cut gizmo, which sometimes // flips the normal of the cut, in which case the contours stay the same but their order may change. - std::sort(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](const CutIsland &a, const CutIsland &b) { return a.hash < b.hash; }); + std::sort(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](CutIsland *a, CutIsland *b) { return a && b && a->hash < b->hash; }); } +void MeshClipper::reset() +{ + if (m_result) { + for (auto it = m_result->cut_islands.begin(); it != m_result->cut_islands.end(); ++it) { + delete *it; + } + std::vector().swap(m_result->cut_islands); + } + m_result.reset(); +} Vec3f MeshRaycaster::get_triangle_normal(size_t facet_idx) const { diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index bfdea3ff2..8d9b84e7c 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -77,6 +77,7 @@ public: // MeshClipper class cuts a mesh and is able to return a triangulated cut. class MeshClipper { public: + ~MeshClipper(); // Set whether the cut should be triangulated and whether a cut // contour should be calculated and shown. void set_behaviour(bool fill_cut, double contour_width); @@ -111,7 +112,7 @@ public: private: void recalculate_triangles(); - + void reset(); Geometry::Transformation m_trafo; const TriangleMesh * m_mesh = nullptr; const TriangleMesh * m_negative_mesh = nullptr; @@ -133,7 +134,7 @@ private: }; struct ClipResult { - std::vector cut_islands; + std::vector cut_islands; Transform3d trafo; // this rotates the cut into world coords }; std::optional m_result; // the cut plane