TriangleMeshSlicer: Optimized out unnecessary transformations.

This commit is contained in:
Vojtech Bubnik 2021-05-18 16:12:49 +02:00
parent 70b4915f9c
commit 78c0199523
3 changed files with 43 additions and 49 deletions

View File

@ -1047,58 +1047,55 @@ static void make_expolygons(const Polygons &loops, const float closing_radius, c
std::vector<Polygons> slice_mesh( std::vector<Polygons> slice_mesh(
const indexed_triangle_set &mesh, const indexed_triangle_set &mesh,
// Unscaled Zs
const std::vector<float> &zs, const std::vector<float> &zs,
const MeshSlicingParams &params, const MeshSlicingParams &params,
std::function<void()> throw_on_cancel) std::function<void()> throw_on_cancel)
{ {
BOOST_LOG_TRIVIAL(debug) << "slice_mesh to polygons"; 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<IntersectionLines> lines; std::vector<IntersectionLines> lines;
{ {
std::vector<float> scaled_zs(zs); std::vector<Vec3i> facets_edges = create_face_neighbors_index(mesh);
for (float &z : scaled_zs) const bool identity = params.trafo.matrix() == Transform3d::Identity().matrix();
z = scaled<float>(z); static constexpr const double s = 1. / SCALING_FACTOR;
if (zs.size() <= 1) {
std::vector<stl_vertex> v_scaled_shared(mesh.vertices); // It likely is not worthwile to copy the vertices. Apply the transformation in place.
for (stl_vertex &v : v_scaled_shared) if (identity)
v *= float(1. / SCALING_FACTOR); lines = slice_make_lines(
mesh.vertices, [](const Vec3f &p) { return Vec3f(scaled<float>(p.x()), scaled<float>(p.y()), p.z()); },
std::vector<Vec3i> facets_edges = create_face_neighbors_index(mesh); mesh.indices, facets_edges, zs, throw_on_cancel);
lines = params.trafo.matrix() == Transform3f::Identity().matrix() ? else {
slice_make_lines(v_scaled_shared, [](const Vec3f &p) { return p; }, mesh.indices, facets_edges, scaled_zs, throw_on_cancel) : // Transform the vertices, scale up in XY, not in Y.
slice_make_lines(v_scaled_shared, [&params](const Vec3f &p) { return params.trafo * p; }, mesh.indices, facets_edges, scaled_zs, throw_on_cancel); auto t = params.trafo;
throw_on_cancel(); t.prescale(Vec3d(s, s, 1.));
auto tf = t.cast<float>();
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<stl_vertex> 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<float>();
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<Polygons> layers = make_loops(lines, params, throw_on_cancel); std::vector<Polygons> layers = make_loops(lines, params, throw_on_cancel);
@ -1154,16 +1151,13 @@ std::vector<ExPolygons> slice_mesh_ex(
layers_p = slice_mesh(mesh, zs, slicing_params, throw_on_cancel); 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<ExPolygons> layers(layers_p.size(), ExPolygons{}); std::vector<ExPolygons> layers(layers_p.size(), ExPolygons{});
tbb::parallel_for( tbb::parallel_for(
tbb::blocked_range<size_t>(0, layers_p.size()), tbb::blocked_range<size_t>(0, layers_p.size()),
[&layers_p, &params, &layers, throw_on_cancel] [&layers_p, &params, &layers, throw_on_cancel]
(const tbb::blocked_range<size_t>& range) { (const tbb::blocked_range<size_t>& range) {
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { 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(); throw_on_cancel();
ExPolygons &expolygons = layers[layer_id]; ExPolygons &expolygons = layers[layer_id];
Slic3r::make_expolygons(layers_p[layer_id], params.closing_radius, params.extra_offset, &expolygons); Slic3r::make_expolygons(layers_p[layer_id], params.closing_radius, params.extra_offset, &expolygons);
@ -1173,7 +1167,7 @@ std::vector<ExPolygons> slice_mesh_ex(
keep_largest_contour_only(expolygons); 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; return layers;
} }

View File

@ -27,7 +27,7 @@ struct MeshSlicingParams
// Mode to apply below slicing_mode_normal_below_layer. Ignored if slicing_mode_nromal_below_layer == 0. // Mode to apply below slicing_mode_normal_below_layer. Ignored if slicing_mode_nromal_below_layer == 0.
SlicingMode mode_below { SlicingMode::Regular }; SlicingMode mode_below { SlicingMode::Regular };
// Transforming faces during the slicing. // Transforming faces during the slicing.
Transform3f trafo { Transform3f::Identity() }; Transform3d trafo { Transform3d::Identity() };
}; };
struct MeshSlicingParamsEx : public MeshSlicingParams struct MeshSlicingParamsEx : public MeshSlicingParams

View File

@ -77,7 +77,7 @@ void MeshClipper::recalculate_triangles()
// Now do the cutting // Now do the cutting
MeshSlicingParamsEx slicing_params; MeshSlicingParamsEx slicing_params;
slicing_params.trafo.rotate(Eigen::Quaternion<double, Eigen::DontAlign>::FromTwoVectors(up, Vec3d::UnitZ()).cast<float>()); slicing_params.trafo.rotate(Eigen::Quaternion<double, Eigen::DontAlign>::FromTwoVectors(up, Vec3d::UnitZ()));
assert(m_mesh->has_shared_vertices()); assert(m_mesh->has_shared_vertices());
std::vector<ExPolygons> list_of_expolys = slice_mesh_ex(m_mesh->its, std::vector<float>{height_mesh}, slicing_params); std::vector<ExPolygons> list_of_expolys = slice_mesh_ex(m_mesh->its, std::vector<float>{height_mesh}, slicing_params);