diff options
author | tamasmeszaros <meszaros.q@gmail.com> | 2019-11-04 16:33:29 +0300 |
---|---|---|
committer | tamasmeszaros <meszaros.q@gmail.com> | 2019-11-04 16:33:29 +0300 |
commit | 7808d09d062b95c7c87c219916cb9b0e5d24eba6 (patch) | |
tree | b6db3af1cf753f0ea910493599220295771d9eaf /src/libslic3r/SLA | |
parent | a8a5a884f9b5d69cb648ef56c3c62ce5ba787484 (diff) |
SLA Contour3D expanded with conversions supporting quads.
Diffstat (limited to 'src/libslic3r/SLA')
-rw-r--r-- | src/libslic3r/SLA/SLABoilerPlate.hpp | 122 | ||||
-rw-r--r-- | src/libslic3r/SLA/SLACommon.cpp | 147 | ||||
-rw-r--r-- | src/libslic3r/SLA/SLACommon.hpp | 75 | ||||
-rw-r--r-- | src/libslic3r/SLA/SLAPad.cpp | 2 | ||||
-rw-r--r-- | src/libslic3r/SLA/SLASupportTreeBuilder.cpp | 2 | ||||
-rw-r--r-- | src/libslic3r/SLA/SLASupportTreeIGL.cpp | 20 |
6 files changed, 240 insertions, 128 deletions
diff --git a/src/libslic3r/SLA/SLABoilerPlate.hpp b/src/libslic3r/SLA/SLABoilerPlate.hpp index 1bb1943ef..9be91ac1d 100644 --- a/src/libslic3r/SLA/SLABoilerPlate.hpp +++ b/src/libslic3r/SLA/SLABoilerPlate.hpp @@ -17,128 +17,6 @@ typedef Eigen::Matrix<int, 4, 1, Eigen::DontAlign> Vec4i; namespace sla { -/// Intermediate struct for a 3D mesh -struct Contour3D { - Pointf3s points; - std::vector<Vec3i> faces3; - std::vector<Vec4i> faces4; - - Contour3D& merge(const Contour3D& ctr) - { - auto N = coord_t(points.size()); - auto N_f3 = faces3.size(); - auto N_f4 = faces4.size(); - - points.insert(points.end(), ctr.points.begin(), ctr.points.end()); - faces3.insert(faces3.end(), ctr.faces3.begin(), ctr.faces3.end()); - faces4.insert(faces4.end(), ctr.faces4.begin(), ctr.faces4.end()); - - for(size_t n = N_f3; n < faces3.size(); n++) { - auto& idx = faces3[n]; idx.x() += N; idx.y() += N; idx.z() += N; - } - - for(size_t n = N_f4; n < faces4.size(); n++) { - auto& idx = faces4[n]; for (int k = 0; k < 4; k++) idx(k) += N; - } - - return *this; - } - - Contour3D& merge(const Pointf3s& triangles) - { - const size_t offs = points.size(); - points.insert(points.end(), triangles.begin(), triangles.end()); - faces3.reserve(faces3.size() + points.size() / 3); - - for(int i = int(offs); i < int(points.size()); i += 3) - faces3.emplace_back(i, i + 1, i + 2); - - return *this; - } - - // Write the index triangle structure to OBJ file for debugging purposes. - void to_obj(std::ostream& stream) - { - for(auto& p : points) { - stream << "v " << p.transpose() << "\n"; - } - - for(auto& f : faces3) { - stream << "f " << (f + Vec3i(1, 1, 1)).transpose() << "\n"; - } - - for(auto& f : faces4) { - stream << "f " << (f + Vec4i(1, 1, 1, 1)).transpose() << "\n"; - } - } - - bool empty() const { return points.empty() || (faces4.empty() && faces3.empty()); } -}; - -using ClusterEl = std::vector<unsigned>; -using ClusteredPoints = std::vector<ClusterEl>; - -// Clustering a set of points by the given distance. -ClusteredPoints cluster(const std::vector<unsigned>& indices, - std::function<Vec3d(unsigned)> pointfn, - double dist, - unsigned max_points); - -ClusteredPoints cluster(const PointSet& points, - double dist, - unsigned max_points); - -ClusteredPoints cluster( - const std::vector<unsigned>& indices, - std::function<Vec3d(unsigned)> pointfn, - std::function<bool(const PointIndexEl&, const PointIndexEl&)> predicate, - unsigned max_points); - - -// Calculate the normals for the selected points (from 'points' set) on the -// mesh. This will call squared distance for each point. -PointSet normals(const PointSet& points, - const EigenMesh3D& convert_mesh, - double eps = 0.05, // min distance from edges - std::function<void()> throw_on_cancel = [](){}, - const std::vector<unsigned>& selected_points = {}); - -/// Mesh from an existing contour. -inline TriangleMesh convert_mesh(const Contour3D& ctour) { - return {ctour.points, ctour.faces3}; -} - -/// Mesh from an evaporating 3D contour -inline TriangleMesh convert_mesh(Contour3D&& ctour) { - return {std::move(ctour.points), std::move(ctour.faces3)}; -} - -inline Contour3D convert_mesh(const TriangleMesh &trmesh) { - Contour3D ret; - ret.points.reserve(trmesh.its.vertices.size()); - ret.faces3.reserve(trmesh.its.indices.size()); - - for (auto &v : trmesh.its.vertices) - ret.points.emplace_back(v.cast<double>()); - - std::copy(trmesh.its.indices.begin(), trmesh.its.indices.end(), - std::back_inserter(ret.faces3)); - - return ret; -} - -inline Contour3D convert_mesh(TriangleMesh &&trmesh) { - Contour3D ret; - ret.points.reserve(trmesh.its.vertices.size()); - - for (auto &v : trmesh.its.vertices) - ret.points.emplace_back(v.cast<double>()); - - ret.faces3.swap(trmesh.its.indices); - - return ret; -} - } } diff --git a/src/libslic3r/SLA/SLACommon.cpp b/src/libslic3r/SLA/SLACommon.cpp new file mode 100644 index 000000000..e6fbed7ec --- /dev/null +++ b/src/libslic3r/SLA/SLACommon.cpp @@ -0,0 +1,147 @@ +#include "SLACommon.hpp" +#include <libslic3r/Format/objparser.hpp> + +namespace Slic3r { namespace sla { + +Contour3D::Contour3D(const TriangleMesh &trmesh) +{ + points.reserve(trmesh.its.vertices.size()); + faces3.reserve(trmesh.its.indices.size()); + + for (auto &v : trmesh.its.vertices) + points.emplace_back(v.cast<double>()); + + std::copy(trmesh.its.indices.begin(), trmesh.its.indices.end(), + std::back_inserter(faces3)); +} + +Contour3D::Contour3D(TriangleMesh &&trmesh) +{ + points.reserve(trmesh.its.vertices.size()); + + for (auto &v : trmesh.its.vertices) + points.emplace_back(v.cast<double>()); + + faces3.swap(trmesh.its.indices); +} + +Contour3D::Contour3D(const EigenMesh3D &emesh) { + points.reserve(size_t(emesh.V().rows())); + faces3.reserve(size_t(emesh.F().rows())); + + for (int r = 0; r < emesh.V().rows(); r++) + points.emplace_back(emesh.V().row(r).cast<double>()); + + for (int i = 0; i < emesh.F().rows(); i++) + faces3.emplace_back(emesh.F().row(i)); +} + +Contour3D &Contour3D::merge(const Contour3D &ctr) +{ + auto N = coord_t(points.size()); + auto N_f3 = faces3.size(); + auto N_f4 = faces4.size(); + + points.insert(points.end(), ctr.points.begin(), ctr.points.end()); + faces3.insert(faces3.end(), ctr.faces3.begin(), ctr.faces3.end()); + faces4.insert(faces4.end(), ctr.faces4.begin(), ctr.faces4.end()); + + for(size_t n = N_f3; n < faces3.size(); n++) { + auto& idx = faces3[n]; idx.x() += N; idx.y() += N; idx.z() += N; + } + + for(size_t n = N_f4; n < faces4.size(); n++) { + auto& idx = faces4[n]; for (int k = 0; k < 4; k++) idx(k) += N; + } + + return *this; +} + +Contour3D &Contour3D::merge(const Pointf3s &triangles) +{ + const size_t offs = points.size(); + points.insert(points.end(), triangles.begin(), triangles.end()); + faces3.reserve(faces3.size() + points.size() / 3); + + for(int i = int(offs); i < int(points.size()); i += 3) + faces3.emplace_back(i, i + 1, i + 2); + + return *this; +} + +void Contour3D::to_obj(std::ostream &stream) +{ + for(auto& p : points) + stream << "v " << p.transpose() << "\n"; + + for(auto& f : faces3) + stream << "f " << (f + Vec3i(1, 1, 1)).transpose() << "\n"; + + for(auto& f : faces4) + stream << "f " << (f + Vec4i(1, 1, 1, 1)).transpose() << "\n"; +} + +void Contour3D::from_obj(std::istream &stream) +{ + ObjParser::ObjData data; + ObjParser::objparse(stream, data); + + points.reserve(data.coordinates.size() / 4 + 1); + auto &coords = data.coordinates; + for (size_t i = 0; i < coords.size(); i += 4) + points.emplace_back(coords[i], coords[i + 1], coords[i + 2]); + + Vec3i triangle; + Vec4i quad; + size_t v = 0; + while(v < data.vertices.size()) { + size_t N = 0; + size_t i = v; + while (data.vertices[v++].coordIdx != -1) ++N; + + std::function<void(int, int)> setfn; + if (N < 3 || N > 4) continue; + else if (N == 3) setfn = [&triangle](int k, int f) { triangle(k) = f; }; + else setfn = [&quad](int k, int f) { quad(k) = f; }; + + for (size_t j = 0; j < N; ++j) + setfn(int(j), data.vertices[i + j].coordIdx); + } +} + +TriangleMesh to_triangle_mesh(const Contour3D &ctour) { + if (ctour.faces4.empty()) return {ctour.points, ctour.faces3}; + + std::vector<Vec3i> triangles; + + triangles.reserve(ctour.faces3.size() + 2 * ctour.faces4.size()); + std::copy(ctour.faces3.begin(), ctour.faces3.end(), + std::back_inserter(triangles)); + + for (auto &quad : ctour.faces4) { + triangles.emplace_back(quad(0), quad(1), quad(2)); + triangles.emplace_back(quad(2), quad(3), quad(0)); + } + + return {ctour.points, std::move(triangles)}; +} + +TriangleMesh to_triangle_mesh(Contour3D &&ctour) { + if (ctour.faces4.empty()) + return {std::move(ctour.points), std::move(ctour.faces3)}; + + std::vector<Vec3i> triangles; + + triangles.reserve(ctour.faces3.size() + 2 * ctour.faces4.size()); + std::copy(ctour.faces3.begin(), ctour.faces3.end(), + std::back_inserter(triangles)); + + for (auto &quad : ctour.faces4) { + triangles.emplace_back(quad(0), quad(1), quad(2)); + triangles.emplace_back(quad(2), quad(3), quad(0)); + } + + return {std::move(ctour.points), std::move(triangles)}; +} + +}} // namespace Slic3r::sla diff --git a/src/libslic3r/SLA/SLACommon.hpp b/src/libslic3r/SLA/SLACommon.hpp index 97b459676..7cdc62662 100644 --- a/src/libslic3r/SLA/SLACommon.hpp +++ b/src/libslic3r/SLA/SLACommon.hpp @@ -5,6 +5,11 @@ #include <vector> #include <Eigen/Geometry> +#include "SLASpatIndex.hpp" + +#include <libslic3r/ExPolygon.hpp> +#include <libslic3r/TriangleMesh.hpp> + // #define SLIC3R_SLA_NEEDS_WINDTREE namespace Slic3r { @@ -12,8 +17,7 @@ namespace Slic3r { // Typedefs from Point.hpp typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> Vec3f; typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> Vec3d; - -class TriangleMesh; +typedef Eigen::Matrix<int, 4, 1, Eigen::DontAlign> Vec4i; namespace sla { @@ -59,9 +63,11 @@ struct SupportPoint bool operator==(const SupportPoint &sp) const { - return (pos == sp.pos) && head_front_radius == sp.head_front_radius && + float rdiff = std::abs(head_front_radius - sp.head_front_radius); + return (pos == sp.pos) && rdiff < float(EPSILON) && is_new_island == sp.is_new_island; } + bool operator!=(const SupportPoint &sp) const { return !(sp == (*this)); } template<class Archive> void serialize(Archive &ar) @@ -72,8 +78,11 @@ struct SupportPoint using SupportPoints = std::vector<SupportPoint>; +struct Contour3D; + /// An index-triangle structure for libIGL functions. Also serves as an -/// alternative (raw) input format for the SLASupportTree +/// alternative (raw) input format for the SLASupportTree. +// Implemented in SLASupportTreeIGL.cpp class EigenMesh3D { class AABBImpl; @@ -86,6 +95,7 @@ public: EigenMesh3D(const TriangleMesh&); EigenMesh3D(const EigenMesh3D& other); + EigenMesh3D(const Contour3D &other); EigenMesh3D& operator=(const EigenMesh3D&); ~EigenMesh3D(); @@ -180,6 +190,63 @@ public: using PointSet = Eigen::MatrixXd; + +/// Dumb vertex mesh consisting of triangles (or) quads. Capable of merging with +/// other meshes of this type and converting to and from other mesh formats. +struct Contour3D { + Pointf3s points; + std::vector<Vec3i> faces3; + std::vector<Vec4i> faces4; + + Contour3D() = default; + Contour3D(const TriangleMesh &trmesh); + Contour3D(TriangleMesh &&trmesh); + Contour3D(const EigenMesh3D &emesh); + + Contour3D& merge(const Contour3D& ctr); + Contour3D& merge(const Pointf3s& triangles); + + // Write the index triangle structure to OBJ file for debugging purposes. + void to_obj(std::ostream& stream); + void from_obj(std::istream &stream); + + inline bool empty() const { return points.empty() || (faces4.empty() && faces3.empty()); } +}; + +using ClusterEl = std::vector<unsigned>; +using ClusteredPoints = std::vector<ClusterEl>; + +// Clustering a set of points by the given distance. +ClusteredPoints cluster(const std::vector<unsigned>& indices, + std::function<Vec3d(unsigned)> pointfn, + double dist, + unsigned max_points); + +ClusteredPoints cluster(const PointSet& points, + double dist, + unsigned max_points); + +ClusteredPoints cluster( + const std::vector<unsigned>& indices, + std::function<Vec3d(unsigned)> pointfn, + std::function<bool(const PointIndexEl&, const PointIndexEl&)> predicate, + unsigned max_points); + + +// Calculate the normals for the selected points (from 'points' set) on the +// mesh. This will call squared distance for each point. +PointSet normals(const PointSet& points, + const EigenMesh3D& convert_mesh, + double eps = 0.05, // min distance from edges + std::function<void()> throw_on_cancel = [](){}, + const std::vector<unsigned>& selected_points = {}); + +/// Mesh from an existing contour. +TriangleMesh to_triangle_mesh(const Contour3D& ctour); + +/// Mesh from an evaporating 3D contour +TriangleMesh to_triangle_mesh(Contour3D&& ctour); + } // namespace sla } // namespace Slic3r diff --git a/src/libslic3r/SLA/SLAPad.cpp b/src/libslic3r/SLA/SLAPad.cpp index d0e802d84..264cfba9f 100644 --- a/src/libslic3r/SLA/SLAPad.cpp +++ b/src/libslic3r/SLA/SLAPad.cpp @@ -677,7 +677,7 @@ void create_pad(const ExPolygons &sup_blueprint, ThrowOnCancel thr) { Contour3D t = create_pad_geometry(sup_blueprint, model_blueprint, cfg, thr); - out.merge(convert_mesh(std::move(t))); + out.merge(to_triangle_mesh(std::move(t))); } std::string PadConfig::validate() const diff --git a/src/libslic3r/SLA/SLASupportTreeBuilder.cpp b/src/libslic3r/SLA/SLASupportTreeBuilder.cpp index 0c276738a..df51c6b5f 100644 --- a/src/libslic3r/SLA/SLASupportTreeBuilder.cpp +++ b/src/libslic3r/SLA/SLASupportTreeBuilder.cpp @@ -466,7 +466,7 @@ const TriangleMesh &SupportTreeBuilder::merged_mesh() const return m_meshcache; } - m_meshcache = convert_mesh(merged); + m_meshcache = to_triangle_mesh(merged); // The mesh will be passed by const-pointer to TriangleMeshSlicer, // which will need this. diff --git a/src/libslic3r/SLA/SLASupportTreeIGL.cpp b/src/libslic3r/SLA/SLASupportTreeIGL.cpp index 05f8b1984..5e10c28c9 100644 --- a/src/libslic3r/SLA/SLASupportTreeIGL.cpp +++ b/src/libslic3r/SLA/SLASupportTreeIGL.cpp @@ -228,6 +228,26 @@ 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(const Contour3D &other) +{ + m_V.resize(Eigen::Index(other.points.size()), 3); + m_F.resize(Eigen::Index(other.faces3.size() + 2 * other.faces4.size()), 3); + + for (Eigen::Index i = 0; i < Eigen::Index(other.points.size()); ++i) + m_V.row(i) = other.points[size_t(i)]; + + for (Eigen::Index i = 0; i < Eigen::Index(other.faces3.size()); ++i) + m_F.row(i) = other.faces3[size_t(i)]; + + size_t N = other.faces3.size() + 2 * other.faces4.size(); + for (size_t i = other.faces3.size(); i < N; i += 2) { + size_t quad_idx = (i - other.faces3.size()) / 2; + auto & quad = other.faces4[quad_idx]; + m_F.row(Eigen::Index(i)) = Vec3i{quad(0), quad(1), quad(2)}; + m_F.row(Eigen::Index(i + 1)) = Vec3i{quad(2), quad(3), quad(0)}; + } +} + EigenMesh3D &EigenMesh3D::operator=(const EigenMesh3D &other) { m_V = other.m_V; |