diff --git a/src/libslic3r/SLA/SLABasePool.cpp b/src/libslic3r/SLA/SLABasePool.cpp index 171d2b8d0..553920f53 100644 --- a/src/libslic3r/SLA/SLABasePool.cpp +++ b/src/libslic3r/SLA/SLABasePool.cpp @@ -53,7 +53,7 @@ Contour3D walls(const Polygon& lower, const Polygon& upper, // Shorthand for the vertex arrays auto& upoints = upper.points, &lpoints = lower.points; - auto& rpts = ret.points; auto& rfaces = ret.indices; + auto& rpts = ret.points; auto& ind = ret.indices; // If the Z levels are flipped, or the offset difference is negative, we // will interpret that as the triangles normals should be inverted. @@ -61,7 +61,7 @@ Contour3D walls(const Polygon& lower, const Polygon& upper, // Copy the points into the mesh, convert them from 2D to 3D rpts.reserve(upoints.size() + lpoints.size()); - rfaces.reserve(2*upoints.size() + 2*lpoints.size()); + ind.reserve(2*upoints.size() + 2*lpoints.size()); const double sf = SCALING_FACTOR; for(auto& p : upoints) rpts.emplace_back(p.x()*sf, p.y()*sf, upper_z_mm); for(auto& p : lpoints) rpts.emplace_back(p.x()*sf, p.y()*sf, lower_z_mm); @@ -121,9 +121,9 @@ Contour3D walls(const Polygon& lower, const Polygon& upper, case Proceed::UPPER: if(!ustarted || uidx != uendidx) { // there are vertices remaining // Get the 3D vertices in order - const Vec3d& p_up1 = rpts[size_t(uidx)]; - const Vec3d& p_low = rpts[size_t(lidx)]; - const Vec3d& p_up2 = rpts[size_t(unextidx)]; + const Vec3d& p_up1 = rpts[uidx]; + const Vec3d& p_low = rpts[lidx]; + const Vec3d& p_up2 = rpts[unextidx]; // Calculate fitness: the average of the two connecting edges double a = offsdiff2 - (distfn(p_up1, p_low) - zdiff2); @@ -133,8 +133,9 @@ Contour3D walls(const Polygon& lower, const Polygon& upper, if(current_fit > prev_fit) { // fit is worse than previously proceed = Proceed::LOWER; } else { // good to go, create the triangle - inverted? rfaces.emplace_back(unextidx, lidx, uidx) : - rfaces.emplace_back(uidx, lidx, unextidx) ; + inverted + ? ind.emplace_back(int(unextidx), int(lidx), int(uidx)) + : ind.emplace_back(int(uidx), int(lidx), int(unextidx)); // Increment the iterators, rotate if necessary ++uidx; ++unextidx; @@ -150,9 +151,9 @@ Contour3D walls(const Polygon& lower, const Polygon& upper, case Proceed::LOWER: // Mode with lower segment, upper vertex. Same structure: if(!lstarted || lidx != lendidx) { - const Vec3d& p_low1 = rpts[size_t(lidx)]; - const Vec3d& p_low2 = rpts[size_t(lnextidx)]; - const Vec3d& p_up = rpts[size_t(uidx)]; + const Vec3d& p_low1 = rpts[lidx]; + const Vec3d& p_low2 = rpts[lnextidx]; + const Vec3d& p_up = rpts[uidx]; double a = offsdiff2 - (distfn(p_up, p_low1) - zdiff2); double b = offsdiff2 - (distfn(p_up, p_low2) - zdiff2); @@ -161,8 +162,9 @@ Contour3D walls(const Polygon& lower, const Polygon& upper, if(current_fit > prev_fit) { proceed = Proceed::UPPER; } else { - inverted? rfaces.emplace_back(uidx, lnextidx, lidx) : - rfaces.emplace_back(lidx, lnextidx, uidx); + inverted + ? ind.emplace_back(int(uidx), int(lnextidx), int(lidx)) + : ind.emplace_back(int(lidx), int(lnextidx), int(uidx)); ++lidx; ++lnextidx; if(lnextidx == rpts.size()) lnextidx = offs; diff --git a/src/libslic3r/SLA/SLABoilerPlate.hpp b/src/libslic3r/SLA/SLABoilerPlate.hpp index 602121af9..be900f532 100644 --- a/src/libslic3r/SLA/SLABoilerPlate.hpp +++ b/src/libslic3r/SLA/SLABoilerPlate.hpp @@ -36,12 +36,10 @@ inline coord_t x(const Vec3crd& p) { return p(0); } inline coord_t y(const Vec3crd& p) { return p(1); } inline coord_t z(const Vec3crd& p) { return p(2); } -using Indices = std::vector<Vec3crd>; - /// Intermediate struct for a 3D mesh struct Contour3D { Pointf3s points; - Indices indices; + std::vector<Vec3i> indices; void merge(const Contour3D& ctr) { auto s3 = coord_t(points.size()); diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index cb2001024..ae033c62f 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -236,13 +236,13 @@ Contour3D cylinder(double r, double h, size_t ssteps, const Vec3d sp = {0,0,0}) // According to the slicing algorithms, we need to aid them with generating // a watertight body. So we create a triangle fan for the upper and lower // ending of the cylinder to close the geometry. - points.emplace_back(jp); size_t ci = points.size() - 1; + points.emplace_back(jp); int ci = int(points.size() - 1); for(int i = 0; i < steps - 1; ++i) indices.emplace_back(i + offs + 1, i + offs, ci); indices.emplace_back(offs, steps + offs - 1, ci); - points.emplace_back(endp); ci = points.size() - 1; + points.emplace_back(endp); ci = int(points.size() - 1); for(int i = 0; i < steps - 1; ++i) indices.emplace_back(ci, i, i + 1); diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index f6a1c429e..324008cf0 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -28,14 +28,16 @@ namespace Slic3r { using SupportTreePtr = std::unique_ptr<sla::SLASupportTree>; -class SLAPrintObject::SupportData { +class SLAPrintObject::SupportData +{ public: - sla::EigenMesh3D emesh; // index-triangle representation - std::vector<sla::SupportPoint> support_points; // all the support points (manual/auto) - SupportTreePtr support_tree_ptr; // the supports - SlicedSupports support_slices; // sliced supports + sla::EigenMesh3D emesh; // index-triangle representation + std::vector<sla::SupportPoint> + support_points; // all the support points (manual/auto) + SupportTreePtr support_tree_ptr; // the supports + SlicedSupports support_slices; // sliced supports - inline SupportData(const TriangleMesh& trmesh): emesh(trmesh) {} + inline SupportData(const TriangleMesh &trmesh) : emesh(trmesh) {} }; namespace { @@ -666,11 +668,11 @@ void SLAPrint::process() double ilhd = m_material_config.initial_layer_height.getFloat(); auto ilh = float(ilhd); - auto ilhs = coord_t(ilhd / SCALING_FACTOR); + auto ilhs = scaled(ilhd); const size_t objcount = m_objects.size(); - const unsigned min_objstatus = 0; // where the per object operations start - const unsigned max_objstatus = 50; // where the per object operations end + static const unsigned min_objstatus = 0; // where the per object operations start + static const unsigned max_objstatus = 50; // where the per object operations end // the coefficient that multiplies the per object status values which // are set up for <0, 100>. They need to be scaled into the whole process @@ -687,31 +689,32 @@ void SLAPrint::process() // Slicing the model object. This method is oversimplified and needs to // be compared with the fff slicing algorithm for verification - auto slice_model = [this, ilhs, ilh, ilhd](SLAPrintObject& po) { + auto slice_model = [this, ilhs, ilh](SLAPrintObject& po) { const TriangleMesh& mesh = po.transformed_mesh(); // We need to prepare the slice index... double lhd = m_objects.front()->m_config.layer_height.getFloat(); float lh = float(lhd); - auto lhs = coord_t(lhd / SCALING_FACTOR); + auto lhs = scaled(lhd); - auto&& bb3d = mesh.bounding_box(); - double minZ = bb3d.min(Z) - po.get_elevation(); - double maxZ = bb3d.max(Z); + auto &&bb3d = mesh.bounding_box(); + double minZ = bb3d.min(Z) - po.get_elevation(); + double maxZ = bb3d.max(Z); + auto minZf = float(minZ); - auto minZs = coord_t(minZ / SCALING_FACTOR); - auto maxZs = coord_t(maxZ / SCALING_FACTOR); + auto minZs = scaled(minZ); + auto maxZs = scaled(maxZ); po.m_slice_index.clear(); size_t cap = size_t(1 + (maxZs - minZs - ilhs) / lhs); po.m_slice_index.reserve(cap); - po.m_slice_index.emplace_back(minZs + ilhs, minZ + ilhd / 2.0, ilh); + po.m_slice_index.emplace_back(minZs + ilhs, minZf + ilh / 2.f, ilh); - for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs) - po.m_slice_index.emplace_back(h, h*SCALING_FACTOR - lhd / 2.0, lh); + for(coord_t h = minZs + ilhs + lhs; h <= maxZs; h += lhs) + po.m_slice_index.emplace_back(h, unscaled<float>(h) - lh / 2.f, lh); // Just get the first record that is form the model: auto slindex_it = @@ -737,15 +740,15 @@ void SLAPrint::process() auto mit = slindex_it; double doffs = m_printer_config.absolute_correction.getFloat(); - coord_t clpr_offs = coord_t(doffs / SCALING_FACTOR); + coord_t clpr_offs = scaled(doffs); for(size_t id = 0; id < po.m_model_slices.size() && mit != po.m_slice_index.end(); id++) { // We apply the printer correction offset here. if(clpr_offs != 0) - po.m_model_slices[id] = - offset_ex(po.m_model_slices[id], clpr_offs); + po.m_model_slices[id] = + offset_ex(po.m_model_slices[id], float(clpr_offs)); mit->set_model_slice_idx(po, id); ++mit; } @@ -949,15 +952,15 @@ void SLAPrint::process() } double doffs = m_printer_config.absolute_correction.getFloat(); - coord_t clpr_offs = coord_t(doffs / SCALING_FACTOR); + coord_t clpr_offs = scaled(doffs); for(size_t i = 0; i < sd->support_slices.size() && i < po.m_slice_index.size(); ++i) { // We apply the printer correction offset here. if(clpr_offs != 0) - sd->support_slices[i] = - offset_ex(sd->support_slices[i], clpr_offs); + sd->support_slices[i] = + offset_ex(sd->support_slices[i], float(clpr_offs)); po.m_slice_index[i].set_support_slice_idx(po, i); } @@ -1063,8 +1066,8 @@ void SLAPrint::process() const int fade_layers_cnt = m_default_object_config.faded_layers.getInt();// 10 // [3;20] - const double width = m_printer_config.display_width.getFloat() / SCALING_FACTOR; - const double height = m_printer_config.display_height.getFloat() / SCALING_FACTOR; + const double width = scaled(m_printer_config.display_width.getFloat()); + const double height = scaled(m_printer_config.display_height.getFloat()); const double display_area = width*height; // get polygons for all instances in the object @@ -1170,13 +1173,20 @@ void SLAPrint::process() ClipperPolygons model_polygons; ClipperPolygons supports_polygons; - size_t c = std::accumulate(layer.slices().begin(), layer.slices().end(), 0u, [](size_t a, const SliceRecord& sr) { - return a + sr.get_slice(soModel).size(); + size_t c = std::accumulate(layer.slices().begin(), + layer.slices().end(), + size_t(0), + [](size_t a, const SliceRecord &sr) { + return a + sr.get_slice(soModel) + .size(); }); model_polygons.reserve(c); - c = std::accumulate(layer.slices().begin(), layer.slices().end(), 0u, [](size_t a, const SliceRecord& sr) { + c = std::accumulate(layer.slices().begin(), + layer.slices().end(), + size_t(0), + [](size_t a, const SliceRecord &sr) { return a + sr.get_slice(soModel).size(); }); @@ -1264,8 +1274,9 @@ void SLAPrint::process() // for(size_t i = 0; i < m_printer_input.size(); ++i) printlayerfn(i); tbb::parallel_for<size_t, decltype(printlayerfn)>(0, m_printer_input.size(), printlayerfn); - m_print_statistics.support_used_material = supports_volume * SCALING_FACTOR * SCALING_FACTOR; - m_print_statistics.objects_used_material = models_volume * SCALING_FACTOR * SCALING_FACTOR; + auto SCALING2 = SCALING_FACTOR * SCALING_FACTOR; + m_print_statistics.support_used_material = supports_volume * SCALING2; + m_print_statistics.objects_used_material = models_volume * SCALING2; // Estimated printing time // A layers count o the highest object @@ -1281,7 +1292,7 @@ void SLAPrint::process() }; // Rasterizing the model objects, and their supports - auto rasterize = [this, max_objstatus]() { + auto rasterize = [this]() { if(canceled()) return; // collect all the keys @@ -1376,11 +1387,12 @@ void SLAPrint::process() tbb::parallel_for<unsigned, decltype(lvlfn)>(0, lvlcnt, lvlfn); // Set statistics values to the printer - m_printer->set_statistics({(m_print_statistics.objects_used_material + m_print_statistics.support_used_material)/1000, - double(m_default_object_config.faded_layers.getInt()), - double(m_print_statistics.slow_layers_count), - double(m_print_statistics.fast_layers_count) - }); + m_printer->set_statistics( + {(m_print_statistics.objects_used_material + + m_print_statistics.support_used_material) / 1000, + double(m_default_object_config.faded_layers.getInt()), + double(m_print_statistics.slow_layers_count), + double(m_print_statistics.fast_layers_count)}); }; using slaposFn = std::function<void(SLAPrintObject&)>; @@ -1408,25 +1420,36 @@ void SLAPrint::process() // TODO: this loop could run in parallel but should not exhaust all the CPU // power available - // Calculate the support structures first before slicing the supports, so that the preview will get displayed ASAP for all objects. - std::vector<SLAPrintObjectStep> step_ranges = { slaposObjectSlice, slaposSliceSupports, slaposCount }; - for (size_t idx_range = 0; idx_range + 1 < step_ranges.size(); ++ idx_range) { - for(SLAPrintObject * po : m_objects) { + // Calculate the support structures first before slicing the supports, + // so that the preview will get displayed ASAP for all objects. + std::vector<SLAPrintObjectStep> step_ranges = {slaposObjectSlice, + slaposSliceSupports, + slaposCount}; - BOOST_LOG_TRIVIAL(info) << "Slicing object " << po->model_object()->name; + for (size_t idx_range = 0; idx_range + 1 < step_ranges.size(); ++idx_range) { + for (SLAPrintObject *po : m_objects) { - for (int s = int(step_ranges[idx_range]); s < int(step_ranges[idx_range + 1]); ++s) { + BOOST_LOG_TRIVIAL(info) + << "Slicing object " << po->model_object()->name; + + for (int s = int(step_ranges[idx_range]); + s < int(step_ranges[idx_range + 1]); + ++s) { auto currentstep = static_cast<SLAPrintObjectStep>(s); - // Cancellation checking. Each step will check for cancellation - // on its own and return earlier gracefully. Just after it returns - // execution gets to this point and throws the canceled signal. + // Cancellation checking. Each step will check for + // cancellation on its own and return earlier gracefully. + // Just after it returns execution gets to this point and + // throws the canceled signal. throw_if_canceled(); st += incr * ostepd; - if(po->m_stepmask[currentstep] && po->set_started(currentstep)) { - m_report_status(*this, st, OBJ_STEP_LABELS(currentstep)); + if (po->m_stepmask[currentstep] + && po->set_started(currentstep)) { + m_report_status(*this, + st, + OBJ_STEP_LABELS(currentstep)); pobj_program[currentstep](*po); throw_if_canceled(); po->set_done(currentstep); @@ -1786,8 +1809,8 @@ std::vector<sla::SupportPoint> SLAPrintObject::transformed_support_points() cons ret.reserve(spts.size()); for(sla::SupportPoint& sp : spts) { - Vec3d transformed_pos = trafo() * Vec3d(sp.pos(0), sp.pos(1), sp.pos(2)); - ret.emplace_back(transformed_pos(0), transformed_pos(1), transformed_pos(2), sp.head_front_radius, sp.is_new_island); + Vec3f transformed_pos = trafo().cast<float>() * sp.pos; + ret.emplace_back(transformed_pos, sp.head_front_radius, sp.is_new_island); } return ret; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index dea468e7a..0c7d92ff2 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -54,15 +54,15 @@ public: bool is_left_handed() const { return m_left_handed; } struct Instance { - Instance(ModelID instance_id, const Point &shift, float rotation) : instance_id(instance_id), shift(shift), rotation(rotation) {} - bool operator==(const Instance &rhs) const { return this->instance_id == rhs.instance_id && this->shift == rhs.shift && this->rotation == rhs.rotation; } - // ID of the corresponding ModelInstance. - ModelID instance_id; - // Slic3r::Point objects in scaled G-code coordinates - Point shift; - // Rotation along the Z axis, in radians. - float rotation; - }; + Instance(ModelID instance_id, const Point &shift, float rotation) : instance_id(instance_id), shift(shift), rotation(rotation) {} + bool operator==(const Instance &rhs) const { return this->instance_id == rhs.instance_id && this->shift == rhs.shift && this->rotation == rhs.rotation; } + // ID of the corresponding ModelInstance. + ModelID instance_id; + // Slic3r::Point objects in scaled G-code coordinates + Point shift; + // Rotation along the Z axis, in radians. + float rotation; + }; const std::vector<Instance>& instances() const { return m_instances; } bool has_mesh(SLAPrintObjectStep step) const; @@ -142,15 +142,19 @@ public: }; private: - - template <class T> inline static T level(const SliceRecord& sr) { + template<class T> inline static T level(const SliceRecord &sr) + { static_assert(std::is_arithmetic<T>::value, "Arithmetic only!"); - return std::is_integral<T>::value ? T(sr.print_level()) : T(sr.slice_level()); + return std::is_integral<T>::value ? T(sr.print_level()) + : T(sr.slice_level()); } - template <class T> inline static SliceRecord create_slice_record(T val) { + template<class T> inline static SliceRecord create_slice_record(T val) + { static_assert(std::is_arithmetic<T>::value, "Arithmetic only!"); - return std::is_integral<T>::value ? SliceRecord{ coord_t(val), 0.f, 0.f } : SliceRecord{ 0, float(val), 0.f }; + return std::is_integral<T>::value + ? SliceRecord{coord_t(val), 0.f, 0.f} + : SliceRecord{0, float(val), 0.f}; } // This is a template method for searching the slice index either by @@ -241,11 +245,11 @@ protected: ~SLAPrintObject(); void config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->m_config.apply(other, ignore_nonexistent); } - void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) - { this->m_config.apply_only(other, keys, ignore_nonexistent); } + void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) + { this->m_config.apply_only(other, keys, ignore_nonexistent); } void set_trafo(const Transform3d& trafo, bool left_handed) { - m_transformed_rmesh.invalidate([this, &trafo, left_handed](){ m_trafo = trafo; m_left_handed = left_handed; }); + m_transformed_rmesh.invalidate([this, &trafo, left_handed](){ m_trafo = trafo; m_left_handed = left_handed; }); } template<class InstVec> inline void set_instances(InstVec&& instances) { m_instances = std::forward<InstVec>(instances); } @@ -380,7 +384,7 @@ public: void set_task(const TaskParams ¶ms) override; void process() override; void finalize() override; - // Returns true if an object step is done on all objects and there's at least one object. + // Returns true if an object step is done on all objects and there's at least one object. bool is_step_done(SLAPrintObjectStep step) const; // Returns true if the last step was finished with success. bool finished() const override { return this->is_step_done(slaposSliceSupports) && this->Inherited::is_step_done(slapsRasterize); } diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 560d74696..e1d247894 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -48,6 +48,19 @@ typedef double coordf_t; //FIXME Better to use an inline function with an explicit return type. //inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); } #define scale_(val) ((val) / SCALING_FACTOR) + +template<class Tf> inline constexpr coord_t scaled(Tf val) +{ + static_assert (std::is_floating_point<Tf>::value, "Floating point only"); + return coord_t(val / Tf(SCALING_FACTOR)); +} + +template<class Tf> inline constexpr Tf unscaled(coord_t val) +{ + static_assert (std::is_floating_point<Tf>::value, "Floating point only"); + return Tf(val * Tf(SCALING_FACTOR)); +} + #define SCALED_EPSILON scale_(EPSILON) #define SLIC3R_DEBUG_OUT_PATH_PREFIX "out/"