From 70cb67430cf8d5284e6ee101d1f2ac189c52699e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 8 Sep 2020 11:40:09 +0200 Subject: [PATCH 1/6] Move rotation from building octree to infill generating --- src/libslic3r/Fill/FillAdaptive.cpp | 27 ++++++++++++++------------- src/libslic3r/Fill/FillAdaptive.hpp | 2 +- src/libslic3r/PrintObject.cpp | 9 ++++++++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index b1a40047d4..db7cab50a0 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -97,11 +97,14 @@ void FillAdaptive::_fill_surface_single( ExPolygon &expolygon, Polylines &polylines_out) { + Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0); + Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones()); + // Store grouped lines by its direction (multiple of 120°) std::vector infill_lines_dir(3); this->generate_infill_lines(this->adapt_fill_octree->root_cube.get(), - this->z, this->adapt_fill_octree->origin,infill_lines_dir, - this->adapt_fill_octree->cubes_properties, + this->z, this->adapt_fill_octree->origin, rotation_matrix, + infill_lines_dir, this->adapt_fill_octree->cubes_properties, int(this->adapt_fill_octree->cubes_properties.size()) - 1); Polylines all_polylines; @@ -186,6 +189,7 @@ void FillAdaptive::generate_infill_lines( FillAdaptive_Internal::Cube *cube, double z_position, const Vec3d &origin, + const Transform3d &rotation_matrix, std::vector &dir_lines_out, const std::vector &cubes_properties, int depth) @@ -197,7 +201,8 @@ void FillAdaptive::generate_infill_lines( return; } - double z_diff = std::abs(z_position - cube->center.z()); + Vec3d cube_center_tranformed = rotation_matrix * cube->center; + double z_diff = std::abs(z_position - cube_center_tranformed.z()); if (z_diff > cubes_properties[depth].height / 2) { @@ -208,14 +213,14 @@ void FillAdaptive::generate_infill_lines( { Point from( scale_((cubes_properties[depth].diagonal_length / 2) * (cubes_properties[depth].line_z_distance - z_diff) / cubes_properties[depth].line_z_distance), - scale_(cubes_properties[depth].line_xy_distance - ((z_position - (cube->center.z() - cubes_properties[depth].line_z_distance)) / sqrt(2)))); + scale_(cubes_properties[depth].line_xy_distance - ((z_position - (cube_center_tranformed.z() - cubes_properties[depth].line_z_distance)) / sqrt(2)))); Point to(-from.x(), from.y()); // Relative to cube center double rotation_angle = (2.0 * M_PI) / 3.0; for (Lines &lines : dir_lines_out) { - Vec3d offset = cube->center - origin; + Vec3d offset = cube_center_tranformed - (rotation_matrix * origin); Point from_abs(from), to_abs(to); from_abs.x() += int(scale_(offset.x())); @@ -235,7 +240,7 @@ void FillAdaptive::generate_infill_lines( { if(child != nullptr) { - generate_infill_lines(child.get(), z_position, origin, dir_lines_out, cubes_properties, depth - 1); + generate_infill_lines(child.get(), z_position, origin, rotation_matrix, dir_lines_out, cubes_properties, depth - 1); } } } @@ -301,14 +306,11 @@ std::unique_ptr FillAdaptive::build_octree( triangle_mesh.require_shared_vertices(); } - Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0); - Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones()); - AABBTreeIndirect::Tree3f aabbTree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set( triangle_mesh.its.vertices, triangle_mesh.its.indices); auto octree = std::make_unique(std::make_unique(cube_center), cube_center, cubes_properties); - FillAdaptive::expand_cube(octree->root_cube.get(), cubes_properties, rotation_matrix, aabbTree, triangle_mesh, int(cubes_properties.size()) - 1); + FillAdaptive::expand_cube(octree->root_cube.get(), cubes_properties, aabbTree, triangle_mesh, int(cubes_properties.size()) - 1); return octree; } @@ -316,7 +318,6 @@ std::unique_ptr FillAdaptive::build_octree( void FillAdaptive::expand_cube( FillAdaptive_Internal::Cube *cube, const std::vector &cubes_properties, - const Transform3d &rotation_matrix, const AABBTreeIndirect::Tree3f &distance_tree, const TriangleMesh &triangle_mesh, int depth) { @@ -337,13 +338,13 @@ void FillAdaptive::expand_cube( for (size_t i = 0; i < 8; ++i) { const Vec3d &child_center = child_centers[i]; - Vec3d child_center_transformed = cube->center + rotation_matrix * (child_center * (cubes_properties[depth].edge_length / 4)); + Vec3d child_center_transformed = cube->center + (child_center * (cubes_properties[depth].edge_length / 4)); if(AABBTreeIndirect::is_any_triangle_in_radius(triangle_mesh.its.vertices, triangle_mesh.its.indices, distance_tree, child_center_transformed, cube_radius_squared)) { cube->children[i] = std::make_unique(child_center_transformed); - FillAdaptive::expand_cube(cube->children[i].get(), cubes_properties, rotation_matrix, distance_tree, triangle_mesh, depth - 1); + FillAdaptive::expand_cube(cube->children[i].get(), cubes_properties, distance_tree, triangle_mesh, depth - 1); } } } diff --git a/src/libslic3r/Fill/FillAdaptive.hpp b/src/libslic3r/Fill/FillAdaptive.hpp index dd7394384c..f337832238 100644 --- a/src/libslic3r/Fill/FillAdaptive.hpp +++ b/src/libslic3r/Fill/FillAdaptive.hpp @@ -63,6 +63,7 @@ protected: FillAdaptive_Internal::Cube *cube, double z_position, const Vec3d & origin, + const Transform3d & rotation_matrix, std::vector & dir_lines_out, const std::vector &cubes_properties, int depth); @@ -78,7 +79,6 @@ public: static void expand_cube( FillAdaptive_Internal::Cube *cube, const std::vector &cubes_properties, - const Transform3d & rotation_matrix, const AABBTreeIndirect::Tree3f &distance_tree, const TriangleMesh & triangle_mesh, int depth); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 474417b1ec..6ebfbc9247 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -444,7 +444,14 @@ std::unique_ptr PrintObject::prepare_adaptive_inf mesh.translate(- unscale(m_center_offset.x()), - unscale(m_center_offset.y()), 0); // Center of the first cube in octree Vec3d mesh_origin = mesh.bounding_box().center(); - return FillAdaptive::build_octree(mesh, adaptive_line_spacing, mesh_origin); + + Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0); + Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones()).inverse(); + + // Rotate mesh and build octree on it with axis-aligned (standart base) cubes + mesh.transform(rotation_matrix); + + return FillAdaptive::build_octree(mesh, adaptive_line_spacing, rotation_matrix * mesh_origin); } void PrintObject::clear_layers() From e55d184a7d4ca992d06575a2230a09dcb4ee910f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 8 Sep 2020 11:48:24 +0200 Subject: [PATCH 2/6] Fix missing initialization in TriangleMesh constructor --- src/libslic3r/TriangleMesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 17edf1b5a8..49fc625af9 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -70,7 +70,7 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector &fac stl_get_size(&stl); } -TriangleMesh::TriangleMesh(const indexed_triangle_set &M) +TriangleMesh::TriangleMesh(const indexed_triangle_set &M) : repaired(false) { stl.stats.type = inmemory; From c26162499908dfb7d86be6cf04cae3bd2b67a46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 8 Sep 2020 11:49:26 +0200 Subject: [PATCH 3/6] A simple version of adaptive cubic support, for testing purposes --- src/libslic3r/Fill/FillAdaptive.hpp | 6 +++++ src/libslic3r/PrintObject.cpp | 38 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/libslic3r/Fill/FillAdaptive.hpp b/src/libslic3r/Fill/FillAdaptive.hpp index f337832238..67a2d0f3fa 100644 --- a/src/libslic3r/Fill/FillAdaptive.hpp +++ b/src/libslic3r/Fill/FillAdaptive.hpp @@ -48,6 +48,12 @@ class FillAdaptive : public Fill public: virtual ~FillAdaptive() {} + static void insert_octant( + FillAdaptive_Internal::Cube * i_cube, + FillAdaptive_Internal::Cube * current, + int depth, + const std::vector &cubes_properties); + protected: virtual Fill* clone() const { return new FillAdaptive(*this); }; virtual void _fill_surface_single( diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 6ebfbc9247..645d36a38c 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -11,6 +11,7 @@ #include "Utils.hpp" #include "AABBTreeIndirect.hpp" #include "Fill/FillAdaptive.hpp" +#include "Format/STL.hpp" #include #include @@ -432,6 +433,8 @@ void PrintObject::generate_support_material() } } +#define ADAPTIVE_SUPPORT_SIMPLE + std::unique_ptr PrintObject::prepare_adaptive_infill_data() { auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this); @@ -445,6 +448,41 @@ std::unique_ptr PrintObject::prepare_adaptive_inf // Center of the first cube in octree Vec3d mesh_origin = mesh.bounding_box().center(); +#ifdef ADAPTIVE_SUPPORT_SIMPLE + if (mesh.its.vertices.empty()) + { + mesh.require_shared_vertices(); + } + + Vec3f vertical(0, 0, 1); + + indexed_triangle_set its_set; + its_set.vertices = mesh.its.vertices; + + // Filter out non overhanging faces + for (size_t i = 0; i < mesh.its.indices.size(); ++i) { + stl_triangle_vertex_indices vertex_idx = mesh.its.indices[i]; + + auto its_calculate_normal = [](const stl_triangle_vertex_indices &index, const std::vector &vertices) { + stl_normal normal = (vertices[index.y()] - vertices[index.x()]).cross(vertices[index.z()] - vertices[index.x()]); + return normal; + }; + + stl_normal normal = its_calculate_normal(vertex_idx, mesh.its.vertices); + stl_normalize_vector(normal); + + if(normal.dot(vertical) >= 0.707) { + its_set.indices.push_back(vertex_idx); + } + } + + mesh = TriangleMesh(its_set); + +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + Slic3r::store_stl(debug_out_path("overhangs.stl").c_str(), &mesh, false); +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ +#endif /* ADAPTIVE_SUPPORT_SIMPLE */ + Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0); Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones()).inverse(); From 680b1b98093264c7307e6694053f323437040a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 9 Sep 2020 09:20:06 +0200 Subject: [PATCH 4/6] Construct octree based on inserted points --- src/libslic3r/Fill/FillAdaptive.cpp | 43 +++++++++++++++++++++++++---- src/libslic3r/Fill/FillAdaptive.hpp | 17 ++++++++---- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index db7cab50a0..4667c30c90 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -91,10 +91,10 @@ std::pair adaptive_fill_line_spacing(const PrintObject &print_ob } void FillAdaptive::_fill_surface_single( - const FillParams ¶ms, + const FillParams ¶ms, unsigned int thickness_layers, - const std::pair &direction, - ExPolygon &expolygon, + const std::pair &direction, + ExPolygon &expolygon, Polylines &polylines_out) { Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0); @@ -329,8 +329,8 @@ void FillAdaptive::expand_cube( } std::vector child_centers = { - Vec3d(-1, -1, -1), Vec3d( 1, -1, -1), Vec3d(-1, 1, -1), Vec3d(-1, -1, 1), - Vec3d( 1, 1, 1), Vec3d(-1, 1, 1), Vec3d( 1, -1, 1), Vec3d( 1, 1, -1) + Vec3d(-1, -1, -1), Vec3d( 1, -1, -1), Vec3d(-1, 1, -1), Vec3d( 1, 1, -1), + Vec3d(-1, -1, 1), Vec3d( 1, -1, 1), Vec3d(-1, 1, 1), Vec3d( 1, 1, 1) }; double cube_radius_squared = (cubes_properties[depth].height * cubes_properties[depth].height) / 16; @@ -349,4 +349,37 @@ void FillAdaptive::expand_cube( } } +void FillAdaptive_Internal::Octree::propagate_point( + Vec3d point, + FillAdaptive_Internal::Cube * current, + int depth, + const std::vector &cubes_properties) +{ + using namespace FillAdaptive_Internal; + + if(depth <= 0) + { + return; + } + + size_t octant_idx = Octree::find_octant(point, current->center); + Cube * child = current->children[octant_idx].get(); + + // Octant not exists, then create it + if(child == nullptr) { + std::vector child_centers = { + Vec3d(-1, -1, -1), Vec3d( 1, -1, -1), Vec3d(-1, 1, -1), Vec3d( 1, 1, -1), + Vec3d(-1, -1, 1), Vec3d( 1, -1, 1), Vec3d(-1, 1, 1), Vec3d( 1, 1, 1) + }; + + const Vec3d &child_center = child_centers[octant_idx]; + Vec3d child_center_transformed = current->center + (child_center * (cubes_properties[depth].edge_length / 4)); + + current->children[octant_idx] = std::make_unique(child_center_transformed); + child = current->children[octant_idx].get(); + } + + Octree::propagate_point(point, child, (depth - 1), cubes_properties); +} + } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillAdaptive.hpp b/src/libslic3r/Fill/FillAdaptive.hpp index 67a2d0f3fa..d384776543 100644 --- a/src/libslic3r/Fill/FillAdaptive.hpp +++ b/src/libslic3r/Fill/FillAdaptive.hpp @@ -35,6 +35,17 @@ namespace FillAdaptive_Internal Octree(std::unique_ptr rootCube, const Vec3d &origin, const std::vector &cubes_properties) : root_cube(std::move(rootCube)), origin(origin), cubes_properties(cubes_properties) {} + + inline static int find_octant(const Vec3d &i_cube, const Vec3d ¤t) + { + return (i_cube.z() > current.z()) * 4 + (i_cube.y() > current.y()) * 2 + (i_cube.x() > current.x()); + } + + static void propagate_point( + Vec3d point, + FillAdaptive_Internal::Cube *current_cube, + int depth, + const std::vector &cubes_properties); }; }; // namespace FillAdaptive_Internal @@ -48,12 +59,6 @@ class FillAdaptive : public Fill public: virtual ~FillAdaptive() {} - static void insert_octant( - FillAdaptive_Internal::Cube * i_cube, - FillAdaptive_Internal::Cube * current, - int depth, - const std::vector &cubes_properties); - protected: virtual Fill* clone() const { return new FillAdaptive(*this); }; virtual void _fill_surface_single( From 8fb9b290b261d3deb86fb7795b54fbd184110167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 9 Sep 2020 09:29:50 +0200 Subject: [PATCH 5/6] A prototype of adaptive support infill --- src/libslic3r/Fill/FillAdaptive.cpp | 115 ++++++++++++++++++++++++++++ src/libslic3r/Fill/FillAdaptive.hpp | 6 ++ src/libslic3r/PrintObject.cpp | 5 ++ 3 files changed, 126 insertions(+) diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index 4667c30c90..d921d8b919 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -382,4 +382,119 @@ void FillAdaptive_Internal::Octree::propagate_point( Octree::propagate_point(point, child, (depth - 1), cubes_properties); } +std::unique_ptr FillAdaptive::build_octree_for_adaptive_support( + TriangleMesh & triangle_mesh, + coordf_t line_spacing, + const Vec3d & cube_center, + const Transform3d &rotation_matrix) +{ + using namespace FillAdaptive_Internal; + + if(line_spacing <= 0 || std::isnan(line_spacing)) + { + return nullptr; + } + + Vec3d bb_size = triangle_mesh.bounding_box().size(); + // The furthest point from the center of the bottom of the mesh bounding box. + double furthest_point = std::sqrt(((bb_size.x() * bb_size.x()) / 4.0) + + ((bb_size.y() * bb_size.y()) / 4.0) + + (bb_size.z() * bb_size.z())); + double max_cube_edge_length = furthest_point * 2; + + std::vector cubes_properties; + for (double edge_length = (line_spacing * 2); edge_length < (max_cube_edge_length * 2); edge_length *= 2) + { + CubeProperties props{}; + props.edge_length = edge_length; + props.height = edge_length * sqrt(3); + props.diagonal_length = edge_length * sqrt(2); + props.line_z_distance = edge_length / sqrt(3); + props.line_xy_distance = edge_length / sqrt(6); + cubes_properties.push_back(props); + } + + if (triangle_mesh.its.vertices.empty()) + { + triangle_mesh.require_shared_vertices(); + } + + AABBTreeIndirect::Tree3f aabbTree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set( + triangle_mesh.its.vertices, triangle_mesh.its.indices); + + auto octree = std::make_unique(std::make_unique(cube_center), cube_center, cubes_properties); + + double cube_edge_length = line_spacing; + size_t max_depth = octree->cubes_properties.size() - 1; + BoundingBoxf3 mesh_bb = triangle_mesh.bounding_box(); + Vec3f vertical(0, 0, 1); + + for (size_t facet_idx = 0; facet_idx < triangle_mesh.stl.facet_start.size(); ++facet_idx) + { + if(triangle_mesh.stl.facet_start[facet_idx].normal.dot(vertical) <= 0.707) + { + // The angle is smaller than PI/4, than infill don't to be there + continue; + } + + stl_vertex v_1 = triangle_mesh.stl.facet_start[facet_idx].vertex[0]; + stl_vertex v_2 = triangle_mesh.stl.facet_start[facet_idx].vertex[1]; + stl_vertex v_3 = triangle_mesh.stl.facet_start[facet_idx].vertex[2]; + + std::vector triangle_vertices = + {Vec3d(v_1.x(), v_1.y(), v_1.z()), + Vec3d(v_2.x(), v_2.y(), v_2.z()), + Vec3d(v_3.x(), v_3.y(), v_3.z())}; + + BoundingBoxf3 triangle_bb(triangle_vertices); + + Vec3d triangle_start_relative = triangle_bb.min - mesh_bb.min; + Vec3d triangle_end_relative = triangle_bb.max - mesh_bb.min; + + Vec3crd triangle_start_idx = Vec3crd( + std::floor(triangle_start_relative.x() / cube_edge_length), + std::floor(triangle_start_relative.y() / cube_edge_length), + std::floor(triangle_start_relative.z() / cube_edge_length)); + Vec3crd triangle_end_idx = Vec3crd( + std::floor(triangle_end_relative.x() / cube_edge_length), + std::floor(triangle_end_relative.y() / cube_edge_length), + std::floor(triangle_end_relative.z() / cube_edge_length)); + + for (int z = triangle_start_idx.z(); z <= triangle_end_idx.z(); ++z) + { + for (int y = triangle_start_idx.y(); y <= triangle_end_idx.y(); ++y) + { + for (int x = triangle_start_idx.x(); x <= triangle_end_idx.x(); ++x) + { + Vec3d cube_center_relative(x * cube_edge_length + (cube_edge_length / 2.0), y * cube_edge_length + (cube_edge_length / 2.0), z * cube_edge_length); + Vec3d cube_center_absolute = cube_center_relative + mesh_bb.min; + + double cube_center_absolute_arr[3] = {cube_center_absolute.x(), cube_center_absolute.y(), cube_center_absolute.z()}; + double distance = 0, cord_u = 0, cord_v = 0; + + double dir[3] = {0.0, 0.0, 1.0}; + + double vert_0[3] = {triangle_vertices[0].x(), + triangle_vertices[0].y(), + triangle_vertices[0].z()}; + double vert_1[3] = {triangle_vertices[1].x(), + triangle_vertices[1].y(), + triangle_vertices[1].z()}; + double vert_2[3] = {triangle_vertices[2].x(), + triangle_vertices[2].y(), + triangle_vertices[2].z()}; + + if(intersect_triangle(cube_center_absolute_arr, dir, vert_0, vert_1, vert_2, &distance, &cord_u, &cord_v) && distance > 0 && distance <= cube_edge_length) + { + Vec3d cube_center_transformed(cube_center_absolute.x(), cube_center_absolute.y(), cube_center_absolute.z() + (cube_edge_length / 2.0)); + Octree::propagate_point(cube_center_transformed, octree->root_cube.get(), max_depth, octree->cubes_properties); + } + } + } + } + } + + return octree; +} + } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillAdaptive.hpp b/src/libslic3r/Fill/FillAdaptive.hpp index d384776543..63043ce4e0 100644 --- a/src/libslic3r/Fill/FillAdaptive.hpp +++ b/src/libslic3r/Fill/FillAdaptive.hpp @@ -93,6 +93,12 @@ public: const AABBTreeIndirect::Tree3f &distance_tree, const TriangleMesh & triangle_mesh, int depth); + + static std::unique_ptr build_octree_for_adaptive_support( + TriangleMesh & triangle_mesh, + coordf_t line_spacing, + const Vec3d & cube_center, + const Transform3d &rotation_matrix); }; // Calculate line spacing for diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 645d36a38c..05debe8abb 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -433,6 +433,7 @@ void PrintObject::generate_support_material() } } +#define ADAPTIVE_SUPPORT #define ADAPTIVE_SUPPORT_SIMPLE std::unique_ptr PrintObject::prepare_adaptive_infill_data() @@ -489,7 +490,11 @@ std::unique_ptr PrintObject::prepare_adaptive_inf // Rotate mesh and build octree on it with axis-aligned (standart base) cubes mesh.transform(rotation_matrix); +#if defined(ADAPTIVE_SUPPORT) && !defined(ADAPTIVE_SUPPORT_SIMPLE) + return FillAdaptive::build_octree_for_adaptive_support(mesh, adaptive_line_spacing, rotation_matrix * mesh_origin, rotation_matrix); +#else return FillAdaptive::build_octree(mesh, adaptive_line_spacing, rotation_matrix * mesh_origin); +#endif } void PrintObject::clear_layers() From f49144a9ef3701e77c2ff812fddfb394c53134ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 10 Sep 2020 16:53:08 +0200 Subject: [PATCH 6/6] Move support cubic infill to separate class. Support infill is enabled in the GUI. --- src/libslic3r/Fill/Fill.cpp | 3 +- src/libslic3r/Fill/FillAdaptive.cpp | 44 +++++++++++++++++++++-------- src/libslic3r/Fill/FillAdaptive.hpp | 26 +++++++++++++++++ src/libslic3r/Fill/FillBase.cpp | 1 + src/libslic3r/Fill/FillBase.hpp | 3 ++ src/libslic3r/Layer.hpp | 4 +-- src/libslic3r/Print.hpp | 2 +- src/libslic3r/PrintConfig.cpp | 2 ++ src/libslic3r/PrintConfig.hpp | 3 +- src/libslic3r/PrintObject.cpp | 32 ++++++++++++--------- 10 files changed, 90 insertions(+), 30 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 9d468a6aa9..d68bc7afb3 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -318,7 +318,7 @@ void export_group_fills_to_svg(const char *path, const std::vector #endif // friend to Layer -void Layer::make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree) +void Layer::make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree, FillAdaptive_Internal::Octree* support_fill_octree) { for (LayerRegion *layerm : m_regions) layerm->fills.clear(); @@ -346,6 +346,7 @@ void Layer::make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree) f->z = this->print_z; f->angle = surface_fill.params.angle; f->adapt_fill_octree = adaptive_fill_octree; + f->support_fill_octree = support_fill_octree; // calculate flow spacing for infill pattern generation bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.flow.bridge; diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index d921d8b919..fb8c665ebd 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -35,7 +35,7 @@ std::pair adaptive_fill_line_spacing(const PrintObject &print_ob const PrintRegionConfig &config = region->config(); bool nonempty = config.fill_density > 0; bool has_adaptive_infill = nonempty && config.fill_pattern == ipAdaptiveCubic; - bool has_support_infill = nonempty && false; // config.fill_pattern == icSupportCubic; + bool has_support_infill = nonempty && config.fill_pattern == ipSupportCubic; region_fill_data.push_back(RegionFillData({ has_adaptive_infill ? Tristate::Maybe : Tristate::No, has_support_infill ? Tristate::Maybe : Tristate::No, @@ -90,22 +90,32 @@ std::pair adaptive_fill_line_spacing(const PrintObject &print_ob return std::make_pair(adaptive_line_spacing, support_line_spacing); } -void FillAdaptive::_fill_surface_single( - const FillParams ¶ms, - unsigned int thickness_layers, - const std::pair &direction, - ExPolygon &expolygon, - Polylines &polylines_out) +void FillAdaptive::_fill_surface_single(const FillParams & params, + unsigned int thickness_layers, + const std::pair &direction, + ExPolygon & expolygon, + Polylines & polylines_out) +{ + if(this->adapt_fill_octree != nullptr) + this->generate_infill(params, thickness_layers, direction, expolygon, polylines_out, this->adapt_fill_octree); +} + +void FillAdaptive::generate_infill(const FillParams & params, + unsigned int thickness_layers, + const std::pair &direction, + ExPolygon & expolygon, + Polylines & polylines_out, + FillAdaptive_Internal::Octree *octree) { Vec3d rotation = Vec3d((5.0 * M_PI) / 4.0, Geometry::deg2rad(215.264), M_PI / 6.0); Transform3d rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation, Vec3d::Ones(), Vec3d::Ones()); // Store grouped lines by its direction (multiple of 120°) std::vector infill_lines_dir(3); - this->generate_infill_lines(this->adapt_fill_octree->root_cube.get(), - this->z, this->adapt_fill_octree->origin, rotation_matrix, - infill_lines_dir, this->adapt_fill_octree->cubes_properties, - int(this->adapt_fill_octree->cubes_properties.size()) - 1); + this->generate_infill_lines(octree->root_cube.get(), + this->z, octree->origin, rotation_matrix, + infill_lines_dir, octree->cubes_properties, + int(octree->cubes_properties.size()) - 1); Polylines all_polylines; all_polylines.reserve(infill_lines_dir[0].size() * 3); @@ -382,7 +392,7 @@ void FillAdaptive_Internal::Octree::propagate_point( Octree::propagate_point(point, child, (depth - 1), cubes_properties); } -std::unique_ptr FillAdaptive::build_octree_for_adaptive_support( +std::unique_ptr FillSupportCubic::build_octree_for_adaptive_support( TriangleMesh & triangle_mesh, coordf_t line_spacing, const Vec3d & cube_center, @@ -497,4 +507,14 @@ std::unique_ptr FillAdaptive::build_octree_for_ad return octree; } +void FillSupportCubic::_fill_surface_single(const FillParams & params, + unsigned int thickness_layers, + const std::pair &direction, + ExPolygon & expolygon, + Polylines & polylines_out) +{ + if (this->support_fill_octree != nullptr) + this->generate_infill(params, thickness_layers, direction, expolygon, polylines_out, this->support_fill_octree); +} + } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillAdaptive.hpp b/src/libslic3r/Fill/FillAdaptive.hpp index 63043ce4e0..45bfde8026 100644 --- a/src/libslic3r/Fill/FillAdaptive.hpp +++ b/src/libslic3r/Fill/FillAdaptive.hpp @@ -81,6 +81,13 @@ protected: static void connect_lines(Lines &lines, Line new_line); + void generate_infill(const FillParams & params, + unsigned int thickness_layers, + const std::pair &direction, + ExPolygon & expolygon, + Polylines & polylines_out, + FillAdaptive_Internal::Octree *octree); + public: static std::unique_ptr build_octree( TriangleMesh &triangle_mesh, @@ -93,7 +100,26 @@ public: const AABBTreeIndirect::Tree3f &distance_tree, const TriangleMesh & triangle_mesh, int depth); +}; +class FillSupportCubic : public FillAdaptive +{ +public: + virtual ~FillSupportCubic() = default; + +protected: + virtual Fill* clone() const { return new FillSupportCubic(*this); }; + + virtual bool no_sort() const { return true; } + + virtual void _fill_surface_single( + const FillParams ¶ms, + unsigned int thickness_layers, + const std::pair &direction, + ExPolygon &expolygon, + Polylines &polylines_out); + +public: static std::unique_ptr build_octree_for_adaptive_support( TriangleMesh & triangle_mesh, coordf_t line_spacing, diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index c1f38dad5c..9001330aae 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -39,6 +39,7 @@ Fill* Fill::new_from_type(const InfillPattern type) case ipHilbertCurve: return new FillHilbertCurve(); case ipOctagramSpiral: return new FillOctagramSpiral(); case ipAdaptiveCubic: return new FillAdaptive(); + case ipSupportCubic: return new FillSupportCubic(); default: throw std::invalid_argument("unknown type"); } } diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 9f70b69e08..dd887b8c3e 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -73,7 +73,10 @@ public: // In scaled coordinates. Bounding box of the 2D projection of the object. BoundingBox bounding_box; + // Octree builds on mesh for usage in the adaptive cubic infill FillAdaptive_Internal::Octree* adapt_fill_octree = nullptr; + // Octree builds on mesh for usage in the support cubic infill + FillAdaptive_Internal::Octree* support_fill_octree = nullptr; public: virtual ~Fill() {} diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 014d2623af..8d5db42fc0 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -138,8 +138,8 @@ public: return false; } void make_perimeters(); - void make_fills() { this->make_fills(nullptr); }; - void make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree); + void make_fills() { this->make_fills(nullptr, nullptr); }; + void make_fills(FillAdaptive_Internal::Octree* adaptive_fill_octree, FillAdaptive_Internal::Octree* support_fill_octree); void make_ironing(); void export_region_slices_to_svg(const char *path) const; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index effb6bde90..98a1314112 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -239,7 +239,7 @@ private: void discover_horizontal_shells(); void combine_infill(); void _generate_support_material(); - std::unique_ptr prepare_adaptive_infill_data(); + std::pair, std::unique_ptr> prepare_adaptive_infill_data(); // XYZ in scaled coordinates Vec3crd m_size; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 718fae365b..72393a3f5a 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -882,6 +882,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("archimedeanchords"); def->enum_values.push_back("octagramspiral"); def->enum_values.push_back("adaptivecubic"); + def->enum_values.push_back("supportcubic"); def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Grid")); def->enum_labels.push_back(L("Triangles")); @@ -896,6 +897,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Archimedean Chords")); def->enum_labels.push_back(L("Octagram Spiral")); def->enum_labels.push_back(L("Adaptive Cubic")); + def->enum_labels.push_back(L("Support Cubic")); def->set_default_value(new ConfigOptionEnum(ipStars)); def = this->add("first_layer_acceleration", coFloat); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 3726444fab..fa7edd10e1 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -39,7 +39,7 @@ enum AuthorizationType { enum InfillPattern : int { ipRectilinear, ipMonotonous, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb, - ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipCount, + ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipCount, }; enum class IroningType { @@ -140,6 +140,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum::g keys_map["archimedeanchords"] = ipArchimedeanChords; keys_map["octagramspiral"] = ipOctagramSpiral; keys_map["adaptivecubic"] = ipAdaptiveCubic; + keys_map["supportcubic"] = ipSupportCubic; } return keys_map; } diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 05debe8abb..a102c32813 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -372,15 +372,15 @@ void PrintObject::infill() this->prepare_infill(); if (this->set_started(posInfill)) { - std::unique_ptr octree = this->prepare_adaptive_infill_data(); + auto [adaptive_fill_octree, support_fill_octree] = this->prepare_adaptive_infill_data(); BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start"; tbb::parallel_for( tbb::blocked_range(0, m_layers.size()), - [this, &octree](const tbb::blocked_range& range) { + [this, &adaptive_fill_octree, &support_fill_octree](const tbb::blocked_range& range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { m_print->throw_if_canceled(); - m_layers[layer_idx]->make_fills(octree.get()); + m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get()); } } ); @@ -433,14 +433,18 @@ void PrintObject::generate_support_material() } } -#define ADAPTIVE_SUPPORT -#define ADAPTIVE_SUPPORT_SIMPLE +//#define ADAPTIVE_SUPPORT_SIMPLE -std::unique_ptr PrintObject::prepare_adaptive_infill_data() +std::pair, std::unique_ptr> PrintObject::prepare_adaptive_infill_data() { + using namespace FillAdaptive_Internal; + auto [adaptive_line_spacing, support_line_spacing] = adaptive_fill_line_spacing(*this); - if (adaptive_line_spacing == 0.) - return std::unique_ptr{}; + + std::unique_ptr adaptive_fill_octree = {}, support_fill_octree = {}; + + if (adaptive_line_spacing == 0. && support_line_spacing == 0.) + return std::make_pair(std::move(adaptive_fill_octree), std::move(support_fill_octree)); TriangleMesh mesh = this->model_object()->raw_mesh(); mesh.transform(m_trafo, true); @@ -490,11 +494,13 @@ std::unique_ptr PrintObject::prepare_adaptive_inf // Rotate mesh and build octree on it with axis-aligned (standart base) cubes mesh.transform(rotation_matrix); -#if defined(ADAPTIVE_SUPPORT) && !defined(ADAPTIVE_SUPPORT_SIMPLE) - return FillAdaptive::build_octree_for_adaptive_support(mesh, adaptive_line_spacing, rotation_matrix * mesh_origin, rotation_matrix); -#else - return FillAdaptive::build_octree(mesh, adaptive_line_spacing, rotation_matrix * mesh_origin); -#endif + if (adaptive_line_spacing != 0.) + adaptive_fill_octree = FillAdaptive::build_octree(mesh, adaptive_line_spacing, rotation_matrix * mesh_origin); + + if (support_line_spacing != 0.) + support_fill_octree = FillSupportCubic::build_octree_for_adaptive_support(mesh, support_line_spacing, rotation_matrix * mesh_origin, rotation_matrix); + + return std::make_pair(std::move(adaptive_fill_octree), std::move(support_fill_octree)); } void PrintObject::clear_layers()