diff options
author | tamasmeszaros <meszaros.q@gmail.com> | 2019-11-12 18:56:06 +0300 |
---|---|---|
committer | tamasmeszaros <meszaros.q@gmail.com> | 2019-11-12 19:11:26 +0300 |
commit | 97811130a18e01ee8c4ae5e59f60918de53ee119 (patch) | |
tree | def10104d5ec68a1d72386b21958a360a9a9bc94 /src/libslic3r/SLA | |
parent | 73ae73348434b110da1a09a83e9d152bb8afda8c (diff) | |
parent | 4e067c42f03bac019066849401fb42f70cacda87 (diff) |
Merge branch 'tm_openvdb_integration' into lm_tm_hollowing
SLAPrintSteps parallel functions now fully adapted to sla::ccr
Diffstat (limited to 'src/libslic3r/SLA')
-rw-r--r-- | src/libslic3r/SLA/Common.cpp | 235 | ||||
-rw-r--r-- | src/libslic3r/SLA/Hollowing.cpp | 26 | ||||
-rw-r--r-- | src/libslic3r/SLA/Hollowing.hpp | 21 | ||||
-rw-r--r-- | src/libslic3r/SLA/RasterWriter.cpp | 2 | ||||
-rw-r--r-- | src/libslic3r/SLA/RasterWriter.hpp | 8 |
5 files changed, 157 insertions, 135 deletions
diff --git a/src/libslic3r/SLA/Common.cpp b/src/libslic3r/SLA/Common.cpp index f85731603..caabdd755 100644 --- a/src/libslic3r/SLA/Common.cpp +++ b/src/libslic3r/SLA/Common.cpp @@ -1,11 +1,13 @@ #include <cmath> #include <libslic3r/SLA/Common.hpp> +#include <libslic3r/SLA/Concurrency.hpp> #include <libslic3r/SLA/SupportTree.hpp> #include <libslic3r/SLA/SpatIndex.hpp> #include <libslic3r/SLA/EigenMesh3D.hpp> #include <libslic3r/SLA/Contour3D.hpp> #include <libslic3r/SLA/Clustering.hpp> + // Workaround: IGL signed_distance.h will define PI in the igl namespace. #undef PI @@ -351,128 +353,131 @@ PointSet normals(const PointSet& points, std::function<void()> thr, // throw on cancel const std::vector<unsigned>& pt_indices) { - if(points.rows() == 0 || mesh.V().rows() == 0 || mesh.F().rows() == 0) + if (points.rows() == 0 || mesh.V().rows() == 0 || mesh.F().rows() == 0) return {}; - + std::vector<unsigned> range = pt_indices; - if(range.empty()) { + if (range.empty()) { range.resize(size_t(points.rows()), 0); std::iota(range.begin(), range.end(), 0); } - - PointSet ret(range.size(), 3); - + + PointSet ret(range.size(), 3); + // for (size_t ridx = 0; ridx < range.size(); ++ridx) - tbb::parallel_for(size_t(0), range.size(), - [&ret, &range, &mesh, &points, thr, eps](size_t ridx) - { - thr(); - auto eidx = Eigen::Index(range[ridx]); - int faceid = 0; - Vec3d p; - - mesh.squared_distance(points.row(eidx), faceid, p); - - auto trindex = mesh.F().row(faceid); - - const Vec3d& p1 = mesh.V().row(trindex(0)); - const Vec3d& p2 = mesh.V().row(trindex(1)); - const Vec3d& p3 = mesh.V().row(trindex(2)); - - // We should check if the point lies on an edge of the hosting triangle. - // If it does then all the other triangles using the same two points - // have to be searched and the final normal should be some kind of - // aggregation of the participating triangle normals. We should also - // consider the cases where the support point lies right on a vertex - // of its triangle. The procedure is the same, get the neighbor - // triangles and calculate an average normal. - - // mark the vertex indices of the edge. ia and ib marks and edge ic - // will mark a single vertex. - int ia = -1, ib = -1, ic = -1; - - if(std::abs(distance(p, p1)) < eps) { - ic = trindex(0); - } - else if(std::abs(distance(p, p2)) < eps) { - ic = trindex(1); - } - else if(std::abs(distance(p, p3)) < eps) { - ic = trindex(2); - } - else if(point_on_edge(p, p1, p2, eps)) { - ia = trindex(0); ib = trindex(1); - } - else if(point_on_edge(p, p2, p3, eps)) { - ia = trindex(1); ib = trindex(2); - } - else if(point_on_edge(p, p1, p3, eps)) { - ia = trindex(0); ib = trindex(2); - } - - // vector for the neigboring triangles including the detected one. - std::vector<Vec3i> neigh; - if(ic >= 0) { // The point is right on a vertex of the triangle - for(int n = 0; n < mesh.F().rows(); ++n) { - thr(); - Vec3i ni = mesh.F().row(n); - if((ni(X) == ic || ni(Y) == ic || ni(Z) == ic)) - neigh.emplace_back(ni); - } - } - else if(ia >= 0 && ib >= 0) { // the point is on and edge - // now get all the neigboring triangles - for(int n = 0; n < mesh.F().rows(); ++n) { - thr(); - Vec3i ni = mesh.F().row(n); - if((ni(X) == ia || ni(Y) == ia || ni(Z) == ia) && - (ni(X) == ib || ni(Y) == ib || ni(Z) == ib)) - neigh.emplace_back(ni); - } - } - - // Calculate the normals for the neighboring triangles - std::vector<Vec3d> neighnorms; neighnorms.reserve(neigh.size()); - for(const Vec3i& tri : neigh) { - const Vec3d& pt1 = mesh.V().row(tri(0)); - const Vec3d& pt2 = mesh.V().row(tri(1)); - const Vec3d& pt3 = mesh.V().row(tri(2)); - Eigen::Vector3d U = pt2 - pt1; - Eigen::Vector3d V = pt3 - pt1; - neighnorms.emplace_back(U.cross(V).normalized()); - } - - // Throw out duplicates. They would cause trouble with summing. We will - // use std::unique which works on sorted ranges. We will sort by the - // coefficient-wise sum of the normals. It should force the same - // elements to be consecutive. - std::sort(neighnorms.begin(), neighnorms.end(), - [](const Vec3d& v1, const Vec3d& v2){ - return v1.sum() < v2.sum(); - }); - - auto lend = std::unique(neighnorms.begin(), neighnorms.end(), - [](const Vec3d& n1, const Vec3d& n2) { - // Compare normals for equivalence. This is controvers stuff. - auto deq = [](double a, double b) { return std::abs(a-b) < 1e-3; }; - return deq(n1(X), n2(X)) && deq(n1(Y), n2(Y)) && deq(n1(Z), n2(Z)); - }); - - if(!neighnorms.empty()) { // there were neighbors to count with - // sum up the normals and then normalize the result again. - // This unification seems to be enough. - Vec3d sumnorm(0, 0, 0); - sumnorm = std::accumulate(neighnorms.begin(), lend, sumnorm); - sumnorm.normalize(); - ret.row(long(ridx)) = sumnorm; - } - else { // point lies safely within its triangle - Eigen::Vector3d U = p2 - p1; - Eigen::Vector3d V = p3 - p1; - ret.row(long(ridx)) = U.cross(V).normalized(); - } + ccr::enumerate( + range.begin(), range.end(), + [&ret, &mesh, &points, thr, eps](unsigned el, size_t ridx) { + thr(); + auto eidx = Eigen::Index(el); + int faceid = 0; + Vec3d p; + + mesh.squared_distance(points.row(eidx), faceid, p); + + auto trindex = mesh.F().row(faceid); + + const Vec3d &p1 = mesh.V().row(trindex(0)); + const Vec3d &p2 = mesh.V().row(trindex(1)); + const Vec3d &p3 = mesh.V().row(trindex(2)); + + // We should check if the point lies on an edge of the hosting + // triangle. If it does then all the other triangles using the + // same two points have to be searched and the final normal should + // be some kind of aggregation of the participating triangle + // normals. We should also consider the cases where the support + // point lies right on a vertex of its triangle. The procedure is + // the same, get the neighbor triangles and calculate an average + // normal. + + // mark the vertex indices of the edge. ia and ib marks and edge + // ic will mark a single vertex. + int ia = -1, ib = -1, ic = -1; + + if (std::abs(distance(p, p1)) < eps) { + ic = trindex(0); + } else if (std::abs(distance(p, p2)) < eps) { + ic = trindex(1); + } else if (std::abs(distance(p, p3)) < eps) { + ic = trindex(2); + } else if (point_on_edge(p, p1, p2, eps)) { + ia = trindex(0); + ib = trindex(1); + } else if (point_on_edge(p, p2, p3, eps)) { + ia = trindex(1); + ib = trindex(2); + } else if (point_on_edge(p, p1, p3, eps)) { + ia = trindex(0); + ib = trindex(2); + } + + // vector for the neigboring triangles including the detected one. + std::vector<Vec3i> neigh; + if (ic >= 0) { // The point is right on a vertex of the triangle + for (int n = 0; n < mesh.F().rows(); ++n) { + thr(); + Vec3i ni = mesh.F().row(n); + if ((ni(X) == ic || ni(Y) == ic || ni(Z) == ic)) + neigh.emplace_back(ni); + } + } else if (ia >= 0 && ib >= 0) { // the point is on and edge + // now get all the neigboring triangles + for (int n = 0; n < mesh.F().rows(); ++n) { + thr(); + Vec3i ni = mesh.F().row(n); + if ((ni(X) == ia || ni(Y) == ia || ni(Z) == ia) && + (ni(X) == ib || ni(Y) == ib || ni(Z) == ib)) + neigh.emplace_back(ni); + } + } + + // Calculate the normals for the neighboring triangles + std::vector<Vec3d> neighnorms; + neighnorms.reserve(neigh.size()); + for (const Vec3i &tri : neigh) { + const Vec3d & pt1 = mesh.V().row(tri(0)); + const Vec3d & pt2 = mesh.V().row(tri(1)); + const Vec3d & pt3 = mesh.V().row(tri(2)); + Eigen::Vector3d U = pt2 - pt1; + Eigen::Vector3d V = pt3 - pt1; + neighnorms.emplace_back(U.cross(V).normalized()); + } + + // Throw out duplicates. They would cause trouble with summing. We + // will use std::unique which works on sorted ranges. We will sort + // by the coefficient-wise sum of the normals. It should force the + // same elements to be consecutive. + std::sort(neighnorms.begin(), neighnorms.end(), + [](const Vec3d &v1, const Vec3d &v2) { + return v1.sum() < v2.sum(); }); - + + auto lend = std::unique(neighnorms.begin(), neighnorms.end(), + [](const Vec3d &n1, const Vec3d &n2) { + // Compare normals for equivalence. + // This is controvers stuff. + auto deq = [](double a, double b) { + return std::abs(a - b) < 1e-3; + }; + return deq(n1(X), n2(X)) && + deq(n1(Y), n2(Y)) && + deq(n1(Z), n2(Z)); + }); + + if (!neighnorms.empty()) { // there were neighbors to count with + // sum up the normals and then normalize the result again. + // This unification seems to be enough. + Vec3d sumnorm(0, 0, 0); + sumnorm = std::accumulate(neighnorms.begin(), lend, sumnorm); + sumnorm.normalize(); + ret.row(long(ridx)) = sumnorm; + } else { // point lies safely within its triangle + Eigen::Vector3d U = p2 - p1; + Eigen::Vector3d V = p3 - p1; + ret.row(long(ridx)) = U.cross(V).normalized(); + } + }); + return ret; } diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index b224bc98c..c3763dbc9 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -1,5 +1,7 @@ #include <functional> +#include <libslic3r/OpenVDBUtils.hpp> +#include <libslic3r/TriangleMesh.hpp> #include <libslic3r/SLA/Hollowing.hpp> #include <libslic3r/SLA/Contour3D.hpp> @@ -98,18 +100,30 @@ remove_cvref_t<Mesh> _generate_interior(Mesh &&mesh, return omesh; } -TriangleMesh generate_interior(const TriangleMesh &mesh, const HollowingConfig &hc, const JobController &ctl) +std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh & mesh, + const HollowingConfig &hc, + const JobController & ctl) { static const double MAX_OVERSAMPL = 7.; - // I can't figure out how to increase the grid resolution through openvdb API - // so the model will be scaled up before conversion and the result scaled - // down. Voxels have a unit size. If I set voxelSize smaller, it scales - // the whole geometry down, and doesn't increase the number of voxels. + // I can't figure out how to increase the grid resolution through openvdb + // API so the model will be scaled up before conversion and the result + // scaled down. Voxels have a unit size. If I set voxelSize smaller, it + // scales the whole geometry down, and doesn't increase the number of + // voxels. // // max 8x upscale, min is native voxel size auto voxel_scale = (1.0 + MAX_OVERSAMPL * hc.quality); - return _generate_interior(mesh, ctl, hc.min_thickness, voxel_scale, hc.closing_distance); + return std::make_unique<TriangleMesh>( + _generate_interior(mesh, ctl, hc.min_thickness, voxel_scale, + hc.closing_distance)); +} + +bool DrainHole::operator==(const DrainHole &sp) const +{ + return (m_pos == sp.m_pos) && (m_normal == sp.m_normal) && + is_approx(m_radius, sp.m_radius) && + is_approx(m_height, sp.m_height); } }} // namespace Slic3r::sla diff --git a/src/libslic3r/SLA/Hollowing.hpp b/src/libslic3r/SLA/Hollowing.hpp index 93a1f90fd..cb5c2bd15 100644 --- a/src/libslic3r/SLA/Hollowing.hpp +++ b/src/libslic3r/SLA/Hollowing.hpp @@ -1,10 +1,14 @@ #ifndef SLA_HOLLOWING_HPP #define SLA_HOLLOWING_HPP -#include <libslic3r/OpenVDBUtils.hpp> +#include <memory> +#include <libslic3r/SLA/Common.hpp> #include <libslic3r/SLA/JobController.hpp> namespace Slic3r { + +class TriangleMesh; + namespace sla { struct HollowingConfig @@ -33,24 +37,19 @@ struct DrainHole , m_height(height) {} - bool operator==(const DrainHole &sp) const - { - return (m_pos == sp.m_pos) && (m_normal == sp.m_normal) && - is_approx(m_radius, sp.m_radius) && - is_approx(m_height, sp.m_height); - } + bool operator==(const DrainHole &sp) const; bool operator!=(const DrainHole &sp) const { return !(sp == (*this)); } - template<class Archive> void serialize(Archive &ar) + template<class Archive> inline void serialize(Archive &ar) { ar(m_pos, m_normal, m_radius, m_height); } }; -TriangleMesh generate_interior(const TriangleMesh &mesh, - const HollowingConfig & = {}, - const JobController &ctl = {}); +std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh &mesh, + const HollowingConfig & = {}, + const JobController &ctl = {}); } } diff --git a/src/libslic3r/SLA/RasterWriter.cpp b/src/libslic3r/SLA/RasterWriter.cpp index b3da0d2a5..0d55b769d 100644 --- a/src/libslic3r/SLA/RasterWriter.cpp +++ b/src/libslic3r/SLA/RasterWriter.cpp @@ -1,4 +1,6 @@ #include <libslic3r/SLA/RasterWriter.hpp> + +#include "libslic3r/PrintConfig.hpp" #include <libslic3r/Zipper.hpp> #include <libslic3r/Time.hpp> diff --git a/src/libslic3r/SLA/RasterWriter.hpp b/src/libslic3r/SLA/RasterWriter.hpp index a7792d55d..62ed44ca8 100644 --- a/src/libslic3r/SLA/RasterWriter.hpp +++ b/src/libslic3r/SLA/RasterWriter.hpp @@ -9,11 +9,13 @@ #include <map> #include <array> -#include "libslic3r/PrintConfig.hpp" - #include <libslic3r/SLA/Raster.hpp> -namespace Slic3r { namespace sla { +namespace Slic3r { + +class DynamicPrintConfig; + +namespace sla { // API to write the zipped sla output layers and metadata. // Implementation uses PNG raster output. |