From 78c01995239e1763e28e563adbd3bcaf68c1564d Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 18 May 2021 16:12:49 +0200 Subject: [PATCH] TriangleMeshSlicer: Optimized out unnecessary transformations. --- src/libslic3r/TriangleMeshSlicer.cpp | 88 +++++++++++++--------------- src/libslic3r/TriangleMeshSlicer.hpp | 2 +- src/slic3r/GUI/MeshUtils.cpp | 2 +- 3 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/libslic3r/TriangleMeshSlicer.cpp b/src/libslic3r/TriangleMeshSlicer.cpp index 06061b034..e7a85e3c5 100644 --- a/src/libslic3r/TriangleMeshSlicer.cpp +++ b/src/libslic3r/TriangleMeshSlicer.cpp @@ -1047,58 +1047,55 @@ static void make_expolygons(const Polygons &loops, const float closing_radius, c std::vector slice_mesh( const indexed_triangle_set &mesh, + // Unscaled Zs const std::vector &zs, const MeshSlicingParams ¶ms, std::function throw_on_cancel) { BOOST_LOG_TRIVIAL(debug) << "slice_mesh to polygons"; - - /* - This method gets called with a list of unscaled Z coordinates and outputs - a vector pointer having the same number of items as the original list. - Each item is a vector of polygons created by slicing our mesh at the - given heights. - This method should basically combine the behavior of the existing - Perl methods defined in lib/Slic3r/TriangleMesh.pm: - - - analyze(): this creates the 'facets_edges' and the 'edges_facets' - tables (we don't need the 'edges' table) - - - slice_facet(): this has to be done for each facet. It generates - intersection lines with each plane identified by the Z list. - The get_layer_range() binary search used to identify the Z range - of the facet is already ported to C++ (see Object.xsp) - - - make_loops(): this has to be done for each layer. It creates polygons - from the lines generated by the previous step. - - At the end, we free the tables generated by analyze() as we don't - need them anymore. - - NOTE: this method accepts a vector of floats because the mesh coordinate - type is float. - */ - std::vector lines; - + { - std::vector scaled_zs(zs); - for (float &z : scaled_zs) - z = scaled(z); - - std::vector v_scaled_shared(mesh.vertices); - for (stl_vertex &v : v_scaled_shared) - v *= float(1. / SCALING_FACTOR); - - std::vector facets_edges = create_face_neighbors_index(mesh); - lines = params.trafo.matrix() == Transform3f::Identity().matrix() ? - slice_make_lines(v_scaled_shared, [](const Vec3f &p) { return p; }, mesh.indices, facets_edges, scaled_zs, throw_on_cancel) : - slice_make_lines(v_scaled_shared, [¶ms](const Vec3f &p) { return params.trafo * p; }, mesh.indices, facets_edges, scaled_zs, throw_on_cancel); - throw_on_cancel(); + std::vector facets_edges = create_face_neighbors_index(mesh); + const bool identity = params.trafo.matrix() == Transform3d::Identity().matrix(); + static constexpr const double s = 1. / SCALING_FACTOR; + if (zs.size() <= 1) { + // It likely is not worthwile to copy the vertices. Apply the transformation in place. + if (identity) + lines = slice_make_lines( + mesh.vertices, [](const Vec3f &p) { return Vec3f(scaled(p.x()), scaled(p.y()), p.z()); }, + mesh.indices, facets_edges, zs, throw_on_cancel); + else { + // Transform the vertices, scale up in XY, not in Y. + auto t = params.trafo; + t.prescale(Vec3d(s, s, 1.)); + auto tf = t.cast(); + slice_make_lines(mesh.vertices, [tf](const Vec3f &p) { return tf * p; }, mesh.indices, facets_edges, zs, throw_on_cancel); + } + } else { + // Copy and scale vertices in XY, don't scale in Z. + // Possibly apply the transformation. + std::vector vertices(mesh.vertices); + if (identity) { + for (stl_vertex &v : vertices) { + // Scale just XY, leave Z unscaled. + v.x() *= float(s); + v.y() *= float(s); + } + } else { + // Transform the vertices, scale up in XY, not in Y. + auto t = params.trafo; + t.prescale(Vec3d(s, s, 1.)); + auto tf = t.cast(); + for (stl_vertex &v : vertices) + v = tf * v; + } + lines = slice_make_lines(vertices, [](const Vec3f &p) { return p; }, mesh.indices, facets_edges, zs, throw_on_cancel); + } } - // v_scaled_shared could be freed here + throw_on_cancel(); std::vector layers = make_loops(lines, params, throw_on_cancel); @@ -1154,16 +1151,13 @@ std::vector slice_mesh_ex( layers_p = slice_mesh(mesh, zs, slicing_params, throw_on_cancel); } - BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - start"; +// BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - start"; std::vector layers(layers_p.size(), ExPolygons{}); tbb::parallel_for( tbb::blocked_range(0, layers_p.size()), [&layers_p, ¶ms, &layers, throw_on_cancel] (const tbb::blocked_range& range) { for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { -#ifdef SLIC3R_TRIANGLEMESH_DEBUG - printf("Layer %zu (slice_z = %.2f):\n", layer_id, z[layer_id]); -#endif throw_on_cancel(); ExPolygons &expolygons = layers[layer_id]; Slic3r::make_expolygons(layers_p[layer_id], params.closing_radius, params.extra_offset, &expolygons); @@ -1173,7 +1167,7 @@ std::vector slice_mesh_ex( keep_largest_contour_only(expolygons); } }); - BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - end"; +// BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - end"; return layers; } diff --git a/src/libslic3r/TriangleMeshSlicer.hpp b/src/libslic3r/TriangleMeshSlicer.hpp index b4914f88b..56ad3d9bf 100644 --- a/src/libslic3r/TriangleMeshSlicer.hpp +++ b/src/libslic3r/TriangleMeshSlicer.hpp @@ -27,7 +27,7 @@ struct MeshSlicingParams // Mode to apply below slicing_mode_normal_below_layer. Ignored if slicing_mode_nromal_below_layer == 0. SlicingMode mode_below { SlicingMode::Regular }; // Transforming faces during the slicing. - Transform3f trafo { Transform3f::Identity() }; + Transform3d trafo { Transform3d::Identity() }; }; struct MeshSlicingParamsEx : public MeshSlicingParams diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index eab46ec2f..c65d2b5a9 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -77,7 +77,7 @@ void MeshClipper::recalculate_triangles() // Now do the cutting MeshSlicingParamsEx slicing_params; - slicing_params.trafo.rotate(Eigen::Quaternion::FromTwoVectors(up, Vec3d::UnitZ()).cast()); + slicing_params.trafo.rotate(Eigen::Quaternion::FromTwoVectors(up, Vec3d::UnitZ())); assert(m_mesh->has_shared_vertices()); std::vector list_of_expolys = slice_mesh_ex(m_mesh->its, std::vector{height_mesh}, slicing_params);