Unified igl calls in MeshRaycaster and EigenMesh3D
MeshRaycaster is still aware of the clipping plane but it now uses EigenMesh3D internally Public interface of both classes is unchanged
This commit is contained in:
parent
645f13a0ae
commit
b4795e1292
@ -189,6 +189,9 @@ public:
|
||||
// Casting a ray on the mesh, returns the distance where the hit occures.
|
||||
hit_result query_ray_hit(const Vec3d &s, const Vec3d &dir) const;
|
||||
|
||||
// Casts a ray on the mesh and returns all hits
|
||||
std::vector<hit_result> query_ray_hits(const Vec3d &s, const Vec3d &dir) const;
|
||||
|
||||
class si_result {
|
||||
double m_value;
|
||||
int m_fidx;
|
||||
|
@ -272,6 +272,31 @@ EigenMesh3D::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<EigenMesh3D::hit_result>
|
||||
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);
|
||||
|
||||
// The sort is necessary, the hits are not always sorted.
|
||||
std::sort(hits.begin(), hits.end(),
|
||||
[](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; });
|
||||
|
||||
// Convert the igl::Hit into hit_result
|
||||
outs.reserve(hits.size());
|
||||
for (const igl::Hit& hit : hits) {
|
||||
outs.emplace_back(EigenMesh3D::hit_result(*this));
|
||||
outs.back().m_t = double(hit.t);
|
||||
outs.back().m_dir = dir;
|
||||
outs.back().m_source = s;
|
||||
if(!std::isinf(hit.t) && !std::isnan(hit.t))
|
||||
outs.back().m_face_id = hit.id;
|
||||
}
|
||||
|
||||
return outs;
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_SLA_NEEDS_WINDTREE
|
||||
EigenMesh3D::si_result EigenMesh3D::signed_distance(const Vec3d &p) const {
|
||||
double sign = 0; double sqdst = 0; int i = 0; Vec3d c;
|
||||
|
@ -5,10 +5,6 @@
|
||||
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
|
||||
// There is an L function in igl that would be overridden by our localization macro.
|
||||
#undef L
|
||||
#include <igl/AABB.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
|
||||
@ -99,59 +95,6 @@ void MeshClipper::recalculate_triangles()
|
||||
}
|
||||
|
||||
|
||||
class MeshRaycaster::AABBWrapper {
|
||||
public:
|
||||
AABBWrapper(const TriangleMesh* mesh);
|
||||
~AABBWrapper() { m_AABB.deinit(); }
|
||||
|
||||
typedef Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>> MapMatrixXfUnaligned;
|
||||
typedef Eigen::Map<const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>> MapMatrixXiUnaligned;
|
||||
igl::AABB<MapMatrixXfUnaligned, 3> m_AABB;
|
||||
|
||||
Vec3f get_hit_pos(const igl::Hit& hit) const;
|
||||
Vec3f get_hit_normal(const igl::Hit& hit) const;
|
||||
|
||||
private:
|
||||
const TriangleMesh* m_mesh;
|
||||
};
|
||||
|
||||
MeshRaycaster::AABBWrapper::AABBWrapper(const TriangleMesh* mesh)
|
||||
: m_mesh(mesh)
|
||||
{
|
||||
m_AABB.init(
|
||||
MapMatrixXfUnaligned(m_mesh->its.vertices.front().data(), m_mesh->its.vertices.size(), 3),
|
||||
MapMatrixXiUnaligned(m_mesh->its.indices.front().data(), m_mesh->its.indices.size(), 3));
|
||||
}
|
||||
|
||||
|
||||
MeshRaycaster::MeshRaycaster(const TriangleMesh& mesh)
|
||||
: m_AABB_wrapper(new AABBWrapper(&mesh)), m_mesh(&mesh)
|
||||
{
|
||||
}
|
||||
|
||||
MeshRaycaster::~MeshRaycaster()
|
||||
{
|
||||
delete m_AABB_wrapper;
|
||||
}
|
||||
|
||||
Vec3f MeshRaycaster::AABBWrapper::get_hit_pos(const igl::Hit& hit) const
|
||||
{
|
||||
const stl_triangle_vertex_indices& indices = m_mesh->its.indices[hit.id];
|
||||
return Vec3f((1-hit.u-hit.v) * m_mesh->its.vertices[indices(0)]
|
||||
+ hit.u * m_mesh->its.vertices[indices(1)]
|
||||
+ hit.v * m_mesh->its.vertices[indices(2)]);
|
||||
}
|
||||
|
||||
|
||||
Vec3f MeshRaycaster::AABBWrapper::get_hit_normal(const igl::Hit& hit) const
|
||||
{
|
||||
const stl_triangle_vertex_indices& indices = m_mesh->its.indices[hit.id];
|
||||
Vec3f a(m_mesh->its.vertices[indices(1)] - m_mesh->its.vertices[indices(0)]);
|
||||
Vec3f b(m_mesh->its.vertices[indices(2)] - m_mesh->its.vertices[indices(0)]);
|
||||
return Vec3f(a.cross(b));
|
||||
}
|
||||
|
||||
|
||||
bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane) const
|
||||
{
|
||||
@ -164,27 +107,20 @@ bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d&
|
||||
::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 0., model_mat.data(), proj_mat.data(), viewport.data(), &pt1(0), &pt1(1), &pt1(2));
|
||||
::gluUnProject(mouse_pos(0), viewport[3] - mouse_pos(1), 1., model_mat.data(), proj_mat.data(), viewport.data(), &pt2(0), &pt2(1), &pt2(2));
|
||||
|
||||
std::vector<igl::Hit> hits;
|
||||
|
||||
Transform3d inv = trafo.inverse();
|
||||
|
||||
pt1 = inv * pt1;
|
||||
pt2 = inv * pt2;
|
||||
|
||||
if (! m_AABB_wrapper->m_AABB.intersect_ray(
|
||||
AABBWrapper::MapMatrixXfUnaligned(m_mesh->its.vertices.front().data(), m_mesh->its.vertices.size(), 3),
|
||||
AABBWrapper::MapMatrixXiUnaligned(m_mesh->its.indices.front().data(), m_mesh->its.indices.size(), 3),
|
||||
pt1.cast<float>(), (pt2-pt1).cast<float>(), hits))
|
||||
std::vector<sla::EigenMesh3D::hit_result> hits = m_emesh.query_ray_hits(pt1, pt2-pt1);
|
||||
if (hits.empty())
|
||||
return false; // no intersection found
|
||||
|
||||
std::sort(hits.begin(), hits.end(), [](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; });
|
||||
|
||||
unsigned i = 0;
|
||||
|
||||
// Remove points that are obscured or cut by the clipping plane
|
||||
if (clipping_plane) {
|
||||
for (i=0; i<hits.size(); ++i)
|
||||
if (! clipping_plane->is_point_clipped(trafo * m_AABB_wrapper->get_hit_pos(hits[i]).cast<double>()))
|
||||
if (! clipping_plane->is_point_clipped(trafo * hits[i].position()))
|
||||
break;
|
||||
|
||||
if (i==hits.size() || (hits.size()-i) % 2 != 0) {
|
||||
@ -195,8 +131,8 @@ bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d&
|
||||
}
|
||||
|
||||
// Now stuff the points in the provided vector and calculate normals if asked about them:
|
||||
position = m_AABB_wrapper->get_hit_pos(hits[i]);
|
||||
normal = m_AABB_wrapper->get_hit_normal(hits[i]);
|
||||
position = hits[i].position().cast<float>();
|
||||
normal = hits[i].normal().cast<float>();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -220,24 +156,21 @@ std::vector<unsigned> MeshRaycaster::get_unobscured_idxs(const Geometry::Transfo
|
||||
|
||||
bool is_obscured = false;
|
||||
// Cast a ray in the direction of the camera and look for intersection with the mesh:
|
||||
std::vector<igl::Hit> hits;
|
||||
std::vector<sla::EigenMesh3D::hit_result> hits;
|
||||
// Offset the start of the ray by EPSILON to account for numerical inaccuracies.
|
||||
if (m_AABB_wrapper->m_AABB.intersect_ray(
|
||||
AABBWrapper::MapMatrixXfUnaligned(m_mesh->its.vertices.front().data(), m_mesh->its.vertices.size(), 3),
|
||||
AABBWrapper::MapMatrixXiUnaligned(m_mesh->its.indices.front().data(), m_mesh->its.indices.size(), 3),
|
||||
inverse_trafo * pt + direction_to_camera_mesh * EPSILON, direction_to_camera_mesh, hits)) {
|
||||
hits = m_emesh.query_ray_hits((inverse_trafo * pt + direction_to_camera_mesh * EPSILON).cast<double>(),
|
||||
direction_to_camera.cast<double>());
|
||||
|
||||
std::sort(hits.begin(), hits.end(), [](const igl::Hit& h1, const igl::Hit& h2) { return h1.t < h2.t; });
|
||||
|
||||
if (! hits.empty()) {
|
||||
// If the closest hit facet normal points in the same direction as the ray,
|
||||
// we are looking through the mesh and should therefore discard the point:
|
||||
if (m_AABB_wrapper->get_hit_normal(hits.front()).dot(direction_to_camera_mesh) > 0.f)
|
||||
if (hits.front().normal().dot(direction_to_camera_mesh.cast<double>()) > 0)
|
||||
is_obscured = true;
|
||||
|
||||
// Eradicate all hits that the caller wants to ignore
|
||||
for (unsigned j=0; j<hits.size(); ++j) {
|
||||
const igl::Hit& hit = hits[j];
|
||||
if (clipping_plane && clipping_plane->is_point_clipped(trafo.get_matrix() * m_AABB_wrapper->get_hit_pos(hit).cast<double>())) {
|
||||
if (clipping_plane && clipping_plane->is_point_clipped(trafo.get_matrix() * hits[j].position())) {
|
||||
hits.erase(hits.begin()+j);
|
||||
--j;
|
||||
}
|
||||
@ -258,17 +191,15 @@ std::vector<unsigned> MeshRaycaster::get_unobscured_idxs(const Geometry::Transfo
|
||||
Vec3f MeshRaycaster::get_closest_point(const Vec3f& point, Vec3f* normal) const
|
||||
{
|
||||
int idx = 0;
|
||||
Eigen::Matrix<float, 1, 3> closest_point;
|
||||
m_AABB_wrapper->m_AABB.squared_distance(
|
||||
AABBWrapper::MapMatrixXfUnaligned(m_mesh->its.vertices.front().data(), m_mesh->its.vertices.size(), 3),
|
||||
AABBWrapper::MapMatrixXiUnaligned(m_mesh->its.indices.front().data(), m_mesh->its.indices.size(), 3),
|
||||
point, idx, closest_point);
|
||||
Vec3d closest_point;
|
||||
m_emesh.squared_distance(point.cast<double>(), idx, closest_point);
|
||||
if (normal) {
|
||||
igl::Hit imag_hit;
|
||||
imag_hit.id = idx;
|
||||
*normal = m_AABB_wrapper->get_hit_normal(imag_hit);
|
||||
const stl_triangle_vertex_indices& indices = m_mesh->its.indices[idx];
|
||||
Vec3f a(m_mesh->its.vertices[indices(1)] - m_mesh->its.vertices[indices(0)]);
|
||||
Vec3f b(m_mesh->its.vertices[indices(2)] - m_mesh->its.vertices[indices(0)]);
|
||||
*normal = Vec3f(a.cross(b));
|
||||
}
|
||||
return closest_point;
|
||||
return closest_point.cast<float>();
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "libslic3r/SLA/SLACommon.hpp"
|
||||
|
||||
|
||||
#include <cfloat>
|
||||
@ -93,8 +94,9 @@ private:
|
||||
|
||||
class MeshRaycaster {
|
||||
public:
|
||||
MeshRaycaster(const TriangleMesh& mesh);
|
||||
~MeshRaycaster();
|
||||
MeshRaycaster(const TriangleMesh& mesh)
|
||||
: m_mesh(&mesh), m_emesh(mesh)
|
||||
{}
|
||||
void set_transformation(const Geometry::Transformation& trafo);
|
||||
void set_camera(const Camera& camera);
|
||||
|
||||
@ -107,9 +109,7 @@ public:
|
||||
Vec3f get_closest_point(const Vec3f& point, Vec3f* normal = nullptr) const;
|
||||
|
||||
private:
|
||||
// PIMPL wrapper around igl::AABB so I don't have to include the header-only IGL here
|
||||
class AABBWrapper;
|
||||
AABBWrapper* m_AABB_wrapper;
|
||||
sla::EigenMesh3D m_emesh;
|
||||
const TriangleMesh* m_mesh = nullptr;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user