From 34f38c4a79e426d4a479bdf33644b2cb77ed0eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 26 Aug 2020 18:15:59 +0200 Subject: [PATCH] Building octree based on distance from mesh --- src/libslic3r/Fill/FillAdaptive.cpp | 86 +++++++++++++++++++++++++++++ src/libslic3r/Fill/FillAdaptive.hpp | 16 ++++++ src/libslic3r/PrintObject.cpp | 23 ++++++++ 3 files changed, 125 insertions(+) diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index cb1138598..ce779ad00 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -1,6 +1,8 @@ #include "../ClipperUtils.hpp" #include "../ExPolygon.hpp" #include "../Surface.hpp" +#include "../Geometry.hpp" +#include "../AABBTreeIndirect.hpp" #include "FillAdaptive.hpp" @@ -16,4 +18,88 @@ void FillAdaptive::_fill_surface_single( } +FillAdaptive_Internal::Octree* FillAdaptive::build_octree( + TriangleMesh &triangleMesh, + coordf_t line_spacing, + const BoundingBoxf3 &printer_volume, + const Vec3d &cube_center) +{ + using namespace FillAdaptive_Internal; + + if(line_spacing <= 0) + { + return nullptr; + } + + // The furthest point from center of bed. + double furthest_point = std::sqrt(((printer_volume.size()[0] * printer_volume.size()[0]) / 4.0) + + ((printer_volume.size()[1] * printer_volume.size()[1]) / 4.0) + + (printer_volume.size()[2] * printer_volume.size()[2])); + 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 (triangleMesh.its.vertices.empty()) + { + triangleMesh.require_shared_vertices(); + } + + Vec3d rotation = Vec3d(Geometry::deg2rad(225.0), Geometry::deg2rad(215.0), Geometry::deg2rad(30.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(triangleMesh.its.vertices, triangleMesh.its.indices); + Octree *octree = new Octree{new Cube{cube_center, cubes_properties.size() - 1, cubes_properties.back()}, cube_center}; + + FillAdaptive::expand_cube(octree->root_cube, cubes_properties, rotation_matrix, aabbTree, triangleMesh); + + return octree; +} + +void FillAdaptive::expand_cube( + FillAdaptive_Internal::Cube *cube, + const std::vector &cubes_properties, + const Transform3d &rotation_matrix, + const AABBTreeIndirect::Tree3f &distanceTree, + const TriangleMesh &triangleMesh) +{ + using namespace FillAdaptive_Internal; + + if (cube == nullptr || cube->depth == 0) + { + return; + } + + 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) + }; + + double cube_radius_squared = (cube->properties.height * cube->properties.height) / 16; + + for (const Vec3d &child_center : child_centers) { + Vec3d child_center_transformed = cube->center + rotation_matrix * (child_center * (cube->properties.edge_length / 4)); + Vec3d closest_point = Vec3d::Zero(); + size_t closest_triangle_idx = 0; + + double distance_squared = AABBTreeIndirect::squared_distance_to_indexed_triangle_set( + triangleMesh.its.vertices, triangleMesh.its.indices, distanceTree, child_center_transformed, + closest_triangle_idx,closest_point); + + if(distance_squared <= cube_radius_squared) { + cube->children.push_back(new Cube{child_center_transformed, cube->depth - 1, cubes_properties[cube->depth - 1]}); + FillAdaptive::expand_cube(cube->children.back(), cubes_properties, rotation_matrix, distanceTree, triangleMesh); + } + } +} + } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillAdaptive.hpp b/src/libslic3r/Fill/FillAdaptive.hpp index e0a97a1b9..49c5276a9 100644 --- a/src/libslic3r/Fill/FillAdaptive.hpp +++ b/src/libslic3r/Fill/FillAdaptive.hpp @@ -1,6 +1,8 @@ #ifndef slic3r_FillAdaptive_hpp_ #define slic3r_FillAdaptive_hpp_ +#include "../AABBTreeIndirect.hpp" + #include "FillBase.hpp" namespace Slic3r { @@ -46,6 +48,20 @@ protected: Polylines &polylines_out); virtual bool no_sort() const { return true; } + +public: + static FillAdaptive_Internal::Octree* build_octree( + TriangleMesh &triangleMesh, + coordf_t line_spacing, + const BoundingBoxf3 &printer_volume, + const Vec3d &cube_center); + + static void expand_cube( + FillAdaptive_Internal::Cube *cube, + const std::vector &cubes_properties, + const Transform3d &rotation_matrix, + const AABBTreeIndirect::Tree3f &distanceTree, + const TriangleMesh &triangleMesh); }; } // namespace Slic3r diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index aecf90771..272ee6e81 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -9,6 +9,8 @@ #include "Surface.hpp" #include "Slicing.hpp" #include "Utils.hpp" +#include "AABBTreeIndirect.hpp" +#include "Fill/FillAdaptive.hpp" #include #include @@ -360,6 +362,8 @@ void PrintObject::prepare_infill() } // for each layer #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + this->prepare_adaptive_infill_data(); + this->set_done(posPrepareInfill); } @@ -428,6 +432,25 @@ void PrintObject::generate_support_material() } } +void PrintObject::prepare_adaptive_infill_data() +{ + float fill_density = this->print()->full_print_config().opt_float("fill_density"); + float infill_extrusion_width = this->print()->full_print_config().opt_float("infill_extrusion_width"); + + coordf_t line_spacing = infill_extrusion_width / ((fill_density / 100.0f) * 0.333333333f); + + BoundingBoxf bed_shape(this->print()->config().bed_shape.values); + BoundingBoxf3 printer_volume(Vec3d(bed_shape.min(0), bed_shape.min(1), 0), + Vec3d(bed_shape.max(0), bed_shape.max(1), this->print()->config().max_print_height)); + + Vec3d model_center = this->model_object()->bounding_box().center(); + model_center(2) = 0.0f; // Set position in Z axis to 0 + // Center of the first cube in octree + + TriangleMesh mesh = this->model_object()->mesh(); + this->m_adapt_fill_octree = FillAdaptive::build_octree(mesh, line_spacing, printer_volume, model_center); +} + void PrintObject::clear_layers() { for (Layer *l : m_layers)