EigenMesh3D now stores TriangleMesh inside, not a mesh in Eigen format
Rotfinder was apparently building the AABB tree needlessly
This commit is contained in:
parent
9224a6a3e6
commit
d85fa8e9ab
4 changed files with 62 additions and 69 deletions
|
@ -184,42 +184,39 @@ void BoxIndex::foreach(std::function<void (const BoxIndexEl &)> fn)
|
|||
class EigenMesh3D::AABBImpl {
|
||||
private:
|
||||
AABBTreeIndirect::Tree3f m_tree;
|
||||
TriangleMesh m_triangle_mesh; // FIXME: There should be no extra copy
|
||||
// maybe even the m_V and m_F are extra. This is just to see the new
|
||||
// AABB tree in action
|
||||
|
||||
public:
|
||||
void init(const TriangleMesh& tmesh)
|
||||
void init(const TriangleMesh& tm)
|
||||
{
|
||||
m_triangle_mesh = tmesh;
|
||||
m_tree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(
|
||||
m_triangle_mesh.its.vertices, m_triangle_mesh.its.indices);
|
||||
tm.its.vertices, tm.its.indices);
|
||||
}
|
||||
|
||||
void intersect_ray(const Eigen::MatrixXd&, const Eigen::MatrixXi&,
|
||||
void intersect_ray(const TriangleMesh& tm,
|
||||
const Vec3d& s, const Vec3d& dir, igl::Hit& hit)
|
||||
{
|
||||
AABBTreeIndirect::intersect_ray_first_hit(m_triangle_mesh.its.vertices,
|
||||
m_triangle_mesh.its.indices,
|
||||
AABBTreeIndirect::intersect_ray_first_hit(tm.its.vertices,
|
||||
tm.its.indices,
|
||||
m_tree,
|
||||
s, dir, hit);
|
||||
}
|
||||
|
||||
void intersect_ray(const Eigen::MatrixXd&, const Eigen::MatrixXi&,
|
||||
void intersect_ray(const TriangleMesh& tm,
|
||||
const Vec3d& s, const Vec3d& dir, std::vector<igl::Hit>& hits)
|
||||
{
|
||||
AABBTreeIndirect::intersect_ray_all_hits(m_triangle_mesh.its.vertices,
|
||||
m_triangle_mesh.its.indices,
|
||||
AABBTreeIndirect::intersect_ray_all_hits(tm.its.vertices,
|
||||
tm.its.indices,
|
||||
m_tree,
|
||||
s, dir, hits);
|
||||
}
|
||||
|
||||
double squared_distance(const Eigen::MatrixXd&, const Eigen::MatrixXi&,
|
||||
double squared_distance(const TriangleMesh& tm,
|
||||
const Vec3d& point, int& i, Eigen::Matrix<double, 1, 3>& closest) {
|
||||
size_t idx_unsigned = 0;
|
||||
Vec3d closest_vec3d(closest);
|
||||
double dist = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(
|
||||
m_triangle_mesh.its.vertices,
|
||||
m_triangle_mesh.its.indices,
|
||||
tm.its.vertices,
|
||||
tm.its.indices,
|
||||
m_tree, point, idx_unsigned, closest_vec3d);
|
||||
i = int(idx_unsigned);
|
||||
closest = closest_vec3d;
|
||||
|
@ -276,12 +273,12 @@ trigger linking error when attempting to use it.
|
|||
}
|
||||
#endif
|
||||
|
||||
EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh): m_aabb(new AABBImpl()) {
|
||||
EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh)
|
||||
: m_aabb(new AABBImpl()), m_tm(tmesh)
|
||||
{
|
||||
auto&& bb = tmesh.bounding_box();
|
||||
m_ground_level += bb.min(Z);
|
||||
|
||||
to_eigen_mesh(tmesh, m_V, m_F);
|
||||
|
||||
// Build the AABB accelaration tree
|
||||
m_aabb->init(tmesh);
|
||||
}
|
||||
|
@ -289,10 +286,10 @@ EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh): m_aabb(new AABBImpl()) {
|
|||
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_tm(other.m_tm), m_ground_level(other.m_ground_level),
|
||||
m_aabb( new AABBImpl(*other.m_aabb) ) {}
|
||||
|
||||
EigenMesh3D::EigenMesh3D(const Contour3D &other)
|
||||
/*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);
|
||||
|
@ -310,12 +307,11 @@ EigenMesh3D::EigenMesh3D(const Contour3D &other)
|
|||
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;
|
||||
m_F = other.m_F;
|
||||
m_tm = other.m_tm;
|
||||
m_ground_level = other.m_ground_level;
|
||||
m_aabb.reset(new AABBImpl(*other.m_aabb)); return *this;
|
||||
}
|
||||
|
@ -333,13 +329,14 @@ EigenMesh3D::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
|
|||
|
||||
#ifdef SLIC3R_HOLE_RAYCASTER
|
||||
if (! m_holes.empty()) {
|
||||
|
||||
// If there are holes, the hit_results will be made by
|
||||
// query_ray_hits (object) and filter_hits (holes):
|
||||
return filter_hits(query_ray_hits(s, dir));
|
||||
}
|
||||
#endif
|
||||
|
||||
m_aabb->intersect_ray(m_V, m_F, s, dir, hit);
|
||||
m_aabb->intersect_ray(m_tm, s, dir, hit);
|
||||
hit_result ret(*this);
|
||||
ret.m_t = double(hit.t);
|
||||
ret.m_dir = dir;
|
||||
|
@ -357,7 +354,7 @@ EigenMesh3D::query_ray_hits(const Vec3d &s, const Vec3d &dir) const
|
|||
{
|
||||
std::vector<EigenMesh3D::hit_result> outs;
|
||||
std::vector<igl::Hit> hits;
|
||||
m_aabb->intersect_ray(m_V, m_F, s, dir, hits);
|
||||
m_aabb->intersect_ray(m_tm, s, dir, hits);
|
||||
|
||||
// The sort is necessary, the hits are not always sorted.
|
||||
std::sort(hits.begin(), hits.end(),
|
||||
|
@ -489,7 +486,7 @@ double EigenMesh3D::squared_distance(const Vec3d &p, int& i, Vec3d& c) const {
|
|||
double sqdst = 0;
|
||||
Eigen::Matrix<double, 1, 3> pp = p;
|
||||
Eigen::Matrix<double, 1, 3> cc;
|
||||
sqdst = m_aabb->squared_distance(m_V, m_F, pp, i, cc);
|
||||
sqdst = m_aabb->squared_distance(m_tm, pp, i, cc);
|
||||
c = cc;
|
||||
return sqdst;
|
||||
}
|
||||
|
@ -523,7 +520,7 @@ 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.vertices().empty() || mesh.indices().empty())
|
||||
return {};
|
||||
|
||||
std::vector<unsigned> range = pt_indices;
|
||||
|
@ -545,11 +542,11 @@ PointSet normals(const PointSet& points,
|
|||
|
||||
mesh.squared_distance(points.row(eidx), faceid, p);
|
||||
|
||||
auto trindex = mesh.F().row(faceid);
|
||||
auto trindex = mesh.indices(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));
|
||||
const Vec3d &p1 = mesh.vertices(trindex(0)).cast<double>();
|
||||
const Vec3d &p2 = mesh.vertices(trindex(1)).cast<double>();
|
||||
const Vec3d &p3 = mesh.vertices(trindex(2)).cast<double>();
|
||||
|
||||
// We should check if the point lies on an edge of the hosting
|
||||
// triangle. If it does then all the other triangles using the
|
||||
|
@ -584,17 +581,17 @@ PointSet normals(const PointSet& points,
|
|||
// 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) {
|
||||
for (size_t n = 0; n < mesh.indices().size(); ++n) {
|
||||
thr();
|
||||
Vec3i ni = mesh.F().row(n);
|
||||
Vec3i ni = mesh.indices(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 (size_t n = 0; n < mesh.indices().size(); ++n) {
|
||||
thr();
|
||||
Vec3i ni = mesh.F().row(n);
|
||||
Vec3i ni = mesh.indices(n);
|
||||
if ((ni(X) == ia || ni(Y) == ia || ni(Z) == ia) &&
|
||||
(ni(X) == ib || ni(Y) == ib || ni(Z) == ib))
|
||||
neigh.emplace_back(ni);
|
||||
|
@ -605,9 +602,9 @@ PointSet normals(const PointSet& points,
|
|||
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));
|
||||
const Vec3d & pt1 = mesh.vertices(tri(0)).cast<double>();
|
||||
const Vec3d & pt2 = mesh.vertices(tri(1)).cast<double>();
|
||||
const Vec3d & pt3 = mesh.vertices(tri(2)).cast<double>();
|
||||
Eigen::Vector3d U = pt2 - pt1;
|
||||
Eigen::Vector3d V = pt3 - pt1;
|
||||
neighnorms.emplace_back(U.cross(V).normalized());
|
||||
|
|
|
@ -28,14 +28,14 @@ Contour3D::Contour3D(TriangleMesh &&trmesh)
|
|||
}
|
||||
|
||||
Contour3D::Contour3D(const EigenMesh3D &emesh) {
|
||||
points.reserve(size_t(emesh.V().rows()));
|
||||
faces3.reserve(size_t(emesh.F().rows()));
|
||||
points.reserve(emesh.vertices().size());
|
||||
faces3.reserve(emesh.indices().size());
|
||||
|
||||
for (int r = 0; r < emesh.V().rows(); r++)
|
||||
points.emplace_back(emesh.V().row(r).cast<double>());
|
||||
for (const Vec3f& vert : emesh.vertices())
|
||||
points.emplace_back(vert.cast<double>());
|
||||
|
||||
for (int i = 0; i < emesh.F().rows(); i++)
|
||||
faces3.emplace_back(emesh.F().row(i));
|
||||
for (const auto& ind : emesh.indices())
|
||||
faces3.emplace_back(ind);
|
||||
}
|
||||
|
||||
Contour3D &Contour3D::merge(const Contour3D &ctr)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define SLA_EIGENMESH3D_H
|
||||
|
||||
#include <libslic3r/SLA/Common.hpp>
|
||||
#include <libslic3r/TriangleMesh.hpp>
|
||||
|
||||
|
||||
// There is an implementation of a hole-aware raycaster that was eventually
|
||||
|
@ -15,8 +16,6 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
class TriangleMesh;
|
||||
|
||||
namespace sla {
|
||||
|
||||
struct Contour3D;
|
||||
|
@ -30,8 +29,7 @@ void to_triangle_mesh(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, Triang
|
|||
class EigenMesh3D {
|
||||
class AABBImpl;
|
||||
|
||||
Eigen::MatrixXd m_V;
|
||||
Eigen::MatrixXi m_F;
|
||||
TriangleMesh m_tm;
|
||||
double m_ground_level = 0, m_gnd_offset = 0;
|
||||
|
||||
std::unique_ptr<AABBImpl> m_aabb;
|
||||
|
@ -59,8 +57,14 @@ public:
|
|||
inline void ground_level_offset(double o) { m_gnd_offset = o; }
|
||||
inline double ground_level_offset() const { return m_gnd_offset; }
|
||||
|
||||
inline const Eigen::MatrixXd& V() const { return m_V; }
|
||||
inline const Eigen::MatrixXi& F() const { return m_F; }
|
||||
const std::vector<stl_vertex>& vertices() const { return m_tm.its.vertices; }
|
||||
const std::vector<stl_triangle_vertex_indices>& indices() const { return m_tm.its.indices; }
|
||||
const stl_vertex& vertices(size_t idx) const {
|
||||
return m_tm.its.vertices[idx];
|
||||
}
|
||||
const stl_triangle_vertex_indices& indices(size_t idx) const {
|
||||
return m_tm.its.indices[idx];
|
||||
}
|
||||
|
||||
// Result of a raycast
|
||||
class hit_result {
|
||||
|
@ -148,10 +152,12 @@ public:
|
|||
}
|
||||
|
||||
Vec3d normal_by_face_id(int face_id) const {
|
||||
auto trindex = F().row(face_id);
|
||||
const Vec3d& p1 = V().row(trindex(0));
|
||||
const Vec3d& p2 = V().row(trindex(1));
|
||||
const Vec3d& p3 = V().row(trindex(2));
|
||||
// FIXME: normals should be cached in TriangleMesh, there should be
|
||||
// no need to recalculate them.
|
||||
auto trindex = this->indices(face_id);
|
||||
const Vec3d& p1 = this->vertices(trindex(0)).cast<double>();
|
||||
const Vec3d& p2 = this->vertices(trindex(1)).cast<double>();
|
||||
const Vec3d& p3 = this->vertices(trindex(2)).cast<double>();
|
||||
Eigen::Vector3d U = p2 - p1;
|
||||
Eigen::Vector3d V = p3 - p1;
|
||||
return U.cross(V).normalized();
|
||||
|
|
|
@ -28,7 +28,7 @@ std::array<double, 3> find_best_rotation(const ModelObject& modelobj,
|
|||
|
||||
// We will use only one instance of this converted mesh to examine different
|
||||
// rotations
|
||||
EigenMesh3D emesh(modelobj.raw_mesh());
|
||||
const TriangleMesh& mesh = modelobj.raw_mesh();
|
||||
|
||||
// For current iteration number
|
||||
unsigned status = 0;
|
||||
|
@ -44,10 +44,10 @@ std::array<double, 3> find_best_rotation(const ModelObject& modelobj,
|
|||
// call the status callback in each iteration but the actual value may be
|
||||
// the same for subsequent iterations (status goes from 0 to 100 but
|
||||
// iterations can be many more)
|
||||
auto objfunc = [&emesh, &status, &statuscb, &stopcond, max_tries]
|
||||
auto objfunc = [&mesh, &status, &statuscb, &stopcond, max_tries]
|
||||
(double rx, double ry, double rz)
|
||||
{
|
||||
EigenMesh3D& m = emesh;
|
||||
const TriangleMesh& m = mesh;
|
||||
|
||||
// prepare the rotation transformation
|
||||
Transform3d rt = Transform3d::Identity();
|
||||
|
@ -68,18 +68,8 @@ std::array<double, 3> 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);
|
||||
|
||||
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;
|
||||
|
||||
// So this is the normal
|
||||
auto n = U.cross(V).normalized();
|
||||
for(size_t i = 0; i < m.stl.facet_start.size(); i++) {
|
||||
Vec3d n = m.stl.facet_start[i].normal.cast<double>();
|
||||
|
||||
// rotate the normal with the current rotation given by the solver
|
||||
n = rt * n;
|
||||
|
|
Loading…
Reference in a new issue