diff --git a/src/libslic3r/SLA/SLACommon.hpp b/src/libslic3r/SLA/SLACommon.hpp
index 6e56b6de7..0a3ee311b 100644
--- a/src/libslic3r/SLA/SLACommon.hpp
+++ b/src/libslic3r/SLA/SLACommon.hpp
@@ -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;
diff --git a/src/libslic3r/SLA/SLASupportTreeIGL.cpp b/src/libslic3r/SLA/SLASupportTreeIGL.cpp
index 03d4a563c..ea2be6be1 100644
--- a/src/libslic3r/SLA/SLASupportTreeIGL.cpp
+++ b/src/libslic3r/SLA/SLASupportTreeIGL.cpp
@@ -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;
diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp
index 62a6813a6..8b37161e9 100644
--- a/src/slic3r/GUI/MeshUtils.cpp
+++ b/src/slic3r/GUI/MeshUtils.cpp
@@ -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>();
 }
 
 
diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp
index e4c4c20d2..8dae2a2f0 100644
--- a/src/slic3r/GUI/MeshUtils.hpp
+++ b/src/slic3r/GUI/MeshUtils.hpp
@@ -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;
 };