diff --git a/src/libslic3r/SLA/SLAAutoSupports.cpp b/src/libslic3r/SLA/SLAAutoSupports.cpp index ee87c6b663..98313be3fd 100644 --- a/src/libslic3r/SLA/SLAAutoSupports.cpp +++ b/src/libslic3r/SLA/SLAAutoSupports.cpp @@ -15,7 +15,7 @@ namespace Slic3r { SLAAutoSupports::SLAAutoSupports(const TriangleMesh& mesh, const sla::EigenMesh3D& emesh, const std::vector& slices, const std::vector& heights, const Config& config, std::function throw_on_cancel) -: m_config(config), m_V(emesh.V), m_F(emesh.F), m_throw_on_cancel(throw_on_cancel) +: m_config(config), m_V(emesh.V()), m_F(emesh.F()), m_throw_on_cancel(throw_on_cancel) { // FIXME: It might be safer to get rid of the rand() calls altogether, because it is probably // not always thread-safe and can be slow if it is. @@ -332,4 +332,4 @@ void SLAAutoSupports::project_upward_onto_mesh(std::vector& points) const } -} // namespace Slic3r \ No newline at end of file +} // namespace Slic3r diff --git a/src/libslic3r/SLA/SLARotfinder.cpp b/src/libslic3r/SLA/SLARotfinder.cpp index e66e26706d..1a91041b78 100644 --- a/src/libslic3r/SLA/SLARotfinder.cpp +++ b/src/libslic3r/SLA/SLARotfinder.cpp @@ -28,7 +28,7 @@ std::array find_best_rotation(const ModelObject& modelobj, // We will use only one instance of this converted mesh to examine different // rotations - EigenMesh3D emesh = to_eigenmesh(modelobj); + EigenMesh3D emesh(modelobj.raw_mesh()); // For current iteration number unsigned status = 0; @@ -68,12 +68,12 @@ std::array find_best_rotation(const ModelObject& modelobj, // area. The current function is only an example of how to optimize. // Later we can add more criteria like the number of overhangs, etc... - for(int i = 0; i < m.F.rows(); i++) { - auto idx = m.F.row(i); + for(int i = 0; i < m.F().rows(); i++) { + auto idx = m.F().row(i); - Vec3d p1 = m.V.row(idx(0)); - Vec3d p2 = m.V.row(idx(1)); - Vec3d p3 = m.V.row(idx(2)); + Vec3d p1 = m.V().row(idx(0)); + Vec3d p2 = m.V().row(idx(1)); + Vec3d p3 = m.V().row(idx(2)); Eigen::Vector3d U = p2 - p1; Eigen::Vector3d V = p3 - p1; diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index c2fcb3c3a4..a105f3e4bb 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -539,23 +539,6 @@ struct Pad { bool empty() const { return tmesh.facets_count() == 0; } }; -EigenMesh3D to_eigenmesh(const Contour3D& cntr) { - EigenMesh3D emesh; - - auto& V = emesh.V; - auto& F = emesh.F; - - V.resize(Eigen::Index(cntr.points.size()), 3); - F.resize(Eigen::Index(cntr.indices.size()), 3); - - for (int i = 0; i < V.rows(); ++i) { - V.row(i) = cntr.points[size_t(i)]; - F.row(i) = cntr.indices[size_t(i)]; - } - - return emesh; -} - // The minimum distance for two support points to remain valid. static const double /*constexpr*/ D_SP = 0.1; @@ -563,46 +546,6 @@ enum { // For indexing Eigen vectors as v(X), v(Y), v(Z) instead of numbers X, Y, Z }; -EigenMesh3D to_eigenmesh(const TriangleMesh& tmesh) { - - const stl_file& stl = tmesh.stl; - - EigenMesh3D outmesh; - - auto&& bb = tmesh.bounding_box(); - outmesh.ground_level += bb.min(Z); - - auto& V = outmesh.V; - auto& F = outmesh.F; - - V.resize(3*stl.stats.number_of_facets, 3); - F.resize(stl.stats.number_of_facets, 3); - for (unsigned int i = 0; i < stl.stats.number_of_facets; ++i) { - const stl_facet* facet = stl.facet_start+i; - V(3*i+0, 0) = double(facet->vertex[0](0)); - V(3*i+0, 1) = double(facet->vertex[0](1)); - V(3*i+0, 2) = double(facet->vertex[0](2)); - - V(3*i+1, 0) = double(facet->vertex[1](0)); - V(3*i+1, 1) = double(facet->vertex[1](1)); - V(3*i+1, 2) = double(facet->vertex[1](2)); - - V(3*i+2, 0) = double(facet->vertex[2](0)); - V(3*i+2, 1) = double(facet->vertex[2](1)); - V(3*i+2, 2) = double(facet->vertex[2](2)); - - F(i, 0) = int(3*i+0); - F(i, 1) = int(3*i+1); - F(i, 2) = int(3*i+2); - } - - return outmesh; -} - -EigenMesh3D to_eigenmesh(const ModelObject& modelobj) { - return to_eigenmesh(modelobj.raw_mesh()); -} - PointSet to_point_set(const std::vector &v) { PointSet ret(v.size(), 3); @@ -618,6 +561,21 @@ double ray_mesh_intersect(const Vec3d& s, const Vec3d& dir, const EigenMesh3D& m); +double pinhead_mesh_intersect(const Vec3d& jp, + const Vec3d& dir, + double r1, + double r2, + const EigenMesh3D& m); + +// Wrapper only +inline double pinhead_mesh_intersect(const Head& head, const EigenMesh3D& m) { + return pinhead_mesh_intersect(head.junction_point(), + head.dir, + head.r_pin_mm, + head.r_back_mm, + m); +} + PointSet normals(const PointSet& points, const EigenMesh3D& mesh, double eps = 0.05, // min distance from edges std::function throw_on_cancel = [](){}); @@ -1789,7 +1747,7 @@ SLASupportTree::SLASupportTree(const PointSet &points, const Controller &ctl): m_impl(new Impl(ctl)) { - m_impl->ground_level = emesh.ground_level - cfg.object_elevation_mm; + m_impl->ground_level = emesh.ground_level() - cfg.object_elevation_mm; generate(points, emesh, cfg, ctl); } diff --git a/src/libslic3r/SLA/SLASupportTree.hpp b/src/libslic3r/SLA/SLASupportTree.hpp index 5a86d4623c..80f0bd68be 100644 --- a/src/libslic3r/SLA/SLASupportTree.hpp +++ b/src/libslic3r/SLA/SLASupportTree.hpp @@ -104,18 +104,40 @@ struct Controller { /// An index-triangle structure for libIGL functions. Also serves as an /// alternative (raw) input format for the SLASupportTree -struct EigenMesh3D { - Eigen::MatrixXd V; - Eigen::MatrixXi F; - double ground_level = 0; +class EigenMesh3D { + class AABBImpl; + + Eigen::MatrixXd m_V; + Eigen::MatrixXi m_F; + double m_ground_level = 0; + + std::unique_ptr m_aabb; +public: + + EigenMesh3D(); + EigenMesh3D(const TriangleMesh&); + + ~EigenMesh3D(); + + EigenMesh3D(const EigenMesh3D& other); +// EigenMesh3D(EigenMesh3D&&) = default; + EigenMesh3D& operator=(const EigenMesh3D&); +// EigenMesh3D& operator=(EigenMesh3D&&) = default; + + inline double ground_level() const { return m_ground_level; } + + inline const Eigen::MatrixXd& V() const { return m_V; } + inline const Eigen::MatrixXi& F() const { return m_F; } + + double query_ray_hit(const Vec3d &s, const Vec3d &dir) const; }; using PointSet = Eigen::MatrixXd; -EigenMesh3D to_eigenmesh(const TriangleMesh& m); +//EigenMesh3D to_eigenmesh(const TriangleMesh& m); // needed for find best rotation -EigenMesh3D to_eigenmesh(const ModelObject& model); +//EigenMesh3D to_eigenmesh(const ModelObject& model); // Simple conversion of 'vector of points' to an Eigen matrix PointSet to_point_set(const std::vector&); diff --git a/src/libslic3r/SLA/SLASupportTreeIGL.cpp b/src/libslic3r/SLA/SLASupportTreeIGL.cpp index 0cc9f14e0f..cacd1ceaa6 100644 --- a/src/libslic3r/SLA/SLASupportTreeIGL.cpp +++ b/src/libslic3r/SLA/SLASupportTreeIGL.cpp @@ -19,6 +19,10 @@ namespace Slic3r { namespace sla { +/* ************************************************************************** + * SpatIndex implementation + * ************************************************************************** */ + class SpatIndex::Impl { public: using BoostIndex = boost::geometry::index::rtree< SpatElement, @@ -78,6 +82,73 @@ size_t SpatIndex::size() const return m_impl->m_store.size(); } +/* **************************************************************************** + * EigenMesh3D implementation + * ****************************************************************************/ + +class EigenMesh3D::AABBImpl: public igl::AABB {}; + +EigenMesh3D::EigenMesh3D(): m_aabb(new AABBImpl()) {} + +EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh): m_aabb(new AABBImpl()) { + static const double dEPS = 1e-6; + + const stl_file& stl = tmesh.stl; + + auto&& bb = tmesh.bounding_box(); + m_ground_level += bb.min(Z); + + Eigen::MatrixXd V; + Eigen::MatrixXi F; + + V.resize(3*stl.stats.number_of_facets, 3); + F.resize(stl.stats.number_of_facets, 3); + for (unsigned int i = 0; i < stl.stats.number_of_facets; ++i) { + const stl_facet* facet = stl.facet_start+i; + V(3*i+0, 0) = double(facet->vertex[0](0)); + V(3*i+0, 1) = double(facet->vertex[0](1)); + V(3*i+0, 2) = double(facet->vertex[0](2)); + + V(3*i+1, 0) = double(facet->vertex[1](0)); + V(3*i+1, 1) = double(facet->vertex[1](1)); + V(3*i+1, 2) = double(facet->vertex[1](2)); + + V(3*i+2, 0) = double(facet->vertex[2](0)); + V(3*i+2, 1) = double(facet->vertex[2](1)); + V(3*i+2, 2) = double(facet->vertex[2](2)); + + F(i, 0) = int(3*i+0); + F(i, 1) = int(3*i+1); + F(i, 2) = int(3*i+2); + } + + // We will convert this to a proper 3d mesh with no duplicate points. + Eigen::VectorXi SVI, SVJ; + igl::remove_duplicate_vertices(V, F, dEPS, m_V, SVI, SVJ, m_F); + + // Build the AABB accelaration tree + m_aabb->init(m_V, m_F); +} + +EigenMesh3D::~EigenMesh3D() {} + +EigenMesh3D::EigenMesh3D(const EigenMesh3D &other): + m_V(other.m_V), m_F(other.m_F), m_ground_level(other.m_ground_level), + m_aabb( new AABBImpl(*other.m_aabb) ) {} + +EigenMesh3D &EigenMesh3D::operator=(const EigenMesh3D &other) +{ + m_V = other.m_V; + m_F = other.m_F; + m_ground_level = other.m_ground_level; + m_aabb.reset(new AABBImpl(*other.m_aabb)); return *this; +} + +double EigenMesh3D::query_ray_hit(const Vec3d &s, const Vec3d &dir) const +{ + return 0; +} + bool point_on_edge(const Vec3d& p, const Vec3d& e1, const Vec3d& e2, double eps = 0.05) { @@ -93,10 +164,10 @@ template double distance(const Vec& pp1, const Vec& pp2) { return std::sqrt(p.transpose() * p); } -PointSet normals(const PointSet& points, const EigenMesh3D& emesh, +PointSet normals(const PointSet& points, const EigenMesh3D& mesh, double eps, std::function throw_on_cancel) { - if(points.rows() == 0 || emesh.V.rows() == 0 || emesh.F.rows() == 0) + if(points.rows() == 0 || mesh.V().rows() == 0 || mesh.F().rows() == 0) return {}; Eigen::VectorXd dists; @@ -105,23 +176,24 @@ PointSet normals(const PointSet& points, const EigenMesh3D& emesh, // We need to remove duplicate vertices and have a true index triangle // structure + /* EigenMesh3D mesh; Eigen::VectorXi SVI, SVJ; static const double dEPS = 1e-6; igl::remove_duplicate_vertices(emesh.V, emesh.F, dEPS, - mesh.V, SVI, SVJ, mesh.F); + mesh.V, SVI, SVJ, mesh.F);*/ - igl::point_mesh_squared_distance( points, mesh.V, mesh.F, dists, I, C); + igl::point_mesh_squared_distance( points, mesh.V(), mesh.F(), dists, I, C); PointSet ret(I.rows(), 3); for(int i = 0; i < I.rows(); i++) { throw_on_cancel(); auto idx = I(i); - auto trindex = mesh.F.row(idx); + auto trindex = mesh.F().row(idx); - const Vec3d& p1 = mesh.V.row(trindex(0)); - const Vec3d& p2 = mesh.V.row(trindex(1)); - const Vec3d& p3 = mesh.V.row(trindex(2)); + 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 than all the other triangles using the same two points @@ -159,18 +231,18 @@ PointSet normals(const PointSet& points, const EigenMesh3D& emesh, // vector for the neigboring triangles including the detected one. std::vector neigh; if(ic >= 0) { // The point is right on a vertex of the triangle - for(int n = 0; n < mesh.F.rows(); ++n) { + for(int n = 0; n < mesh.F().rows(); ++n) { throw_on_cancel(); - Vec3i ni = mesh.F.row(n); + 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) { + for(int n = 0; n < mesh.F().rows(); ++n) { throw_on_cancel(); - Vec3i ni = mesh.F.row(n); + 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); @@ -180,9 +252,9 @@ PointSet normals(const PointSet& points, const EigenMesh3D& emesh, // Calculate the normals for the neighboring triangles std::vector 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)); + 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()); @@ -228,10 +300,24 @@ double ray_mesh_intersect(const Vec3d& s, { igl::Hit hit; hit.t = std::numeric_limits::infinity(); - igl::ray_mesh_intersect(s, dir, m.V, m.F, hit); + + // Fck: this does not use any kind of spatial index acceleration... + igl::ray_mesh_intersect(s, dir, m.V(), m.F(), hit); return double(hit.t); } +// An enhanced version of ray_mesh_intersect for the pinheads. This will shoot +// multiple rays to detect collisions more accurately. +double pinhead_mesh_intersect(const Vec3d& jp, + const Vec3d& dir, + double r1, + double r2, + const EigenMesh3D& m) +{ + + return 0; +} + // Clustering a set of points by the given criteria ClusteredPoints cluster( const sla::PointSet& points, @@ -309,53 +395,5 @@ ClusteredPoints cluster( return result; } -using Segments = std::vector>; - -Segments model_boundary(const EigenMesh3D& emesh, double offs) -{ - Segments ret; - Polygons pp; - pp.reserve(size_t(emesh.F.rows())); - - for (int i = 0; i < emesh.F.rows(); i++) { - auto trindex = emesh.F.row(i); - auto& p1 = emesh.V.row(trindex(0)); - auto& p2 = emesh.V.row(trindex(1)); - auto& p3 = emesh.V.row(trindex(2)); - - Polygon p; - p.points.resize(3); - p.points[0] = Point::new_scale(p1(X), p1(Y)); - p.points[1] = Point::new_scale(p2(X), p2(Y)); - p.points[2] = Point::new_scale(p3(X), p3(Y)); - p.make_counter_clockwise(); - pp.emplace_back(p); - } - - ExPolygons merged = union_ex(Slic3r::offset(pp, float(scale_(offs))), true); - - for(auto& expoly : merged) { - auto lines = expoly.lines(); - for(Line& l : lines) { - Vec2d a(l.a(X) * SCALING_FACTOR, l.a(Y) * SCALING_FACTOR); - Vec2d b(l.b(X) * SCALING_FACTOR, l.b(Y) * SCALING_FACTOR); - ret.emplace_back(std::make_pair(a, b)); - } - } - - return ret; -} - -//struct SegmentIndex { - -//}; - -//using SegmentIndexEl = std::pair; - -//SegmentIndexEl - - - - } } diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 5cddadb5b1..445c785763 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -508,7 +508,7 @@ void SLAPrint::process() auto support_points = [this, ilh](SLAPrintObject& po) { const ModelObject& mo = *po.m_model_object; po.m_supportdata.reset(new SLAPrintObject::SupportData()); - po.m_supportdata->emesh = sla::to_eigenmesh(po.transformed_mesh()); + po.m_supportdata->emesh = EigenMesh3D(po.transformed_mesh()); BOOST_LOG_TRIVIAL(debug) << "Support point count " << mo.sla_support_points.size();