OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::MeshRaycaster Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/MeshUtils.hpp>

Collaboration diagram for Slic3r::GUI::MeshRaycaster:

Public Member Functions

 MeshRaycaster (std::shared_ptr< const TriangleMesh > mesh)
 MeshRaycaster (const TriangleMesh &mesh)
bool unproject_on_mesh (const Vec2d &mouse_pos, const Transform3d &trafo, const Camera &camera, Vec3f &position, Vec3f &normal, const ClippingPlane *clipping_plane=nullptr, size_t *facet_idx=nullptr, bool sinking_limit=true) const
const AABBMesh & get_aabb_mesh () const
bool intersects_line (Vec3d point, Vec3d direction, const Transform3d &trafo) const
std::vector< unsigned > get_unobscured_idxs (const Geometry::Transformation &trafo, const Camera &camera, const std::vector< Vec3f > &points, const ClippingPlane *clipping_plane=nullptr) const
bool closest_hit (const Vec2d &mouse_pos, const Transform3d &trafo, const Camera &camera, Vec3f &position, Vec3f &normal, const ClippingPlane *clipping_plane=nullptr, size_t *facet_idx=nullptr) const
Vec3f get_closest_point (const Vec3f &point, Vec3f *normal=nullptr) const
int get_closest_facet (const Vec3f &point) const
Vec3f get_triangle_normal (size_t facet_idx) const

Static Public Member Functions

static void line_from_mouse_pos (const Vec2d &mouse_pos, const Transform3d &trafo, const Camera &camera, Vec3d &point, Vec3d &direction)

Private Attributes

std::shared_ptr< const TriangleMesh > m_mesh
AABBMesh m_emesh
std::vector< stl_normal > m_normals

Detailed Description

Constructor & Destructor Documentation

◆ MeshRaycaster() [1/2]

Slic3r::GUI::MeshRaycaster::MeshRaycaster ( std::shared_ptr< const TriangleMesh > mesh)
inlineexplicit
173 : m_mesh(std::move(mesh))
174 , m_emesh(*m_mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length
176 {
177 assert(m_mesh);
178 }
std::shared_ptr< const TriangleMesh > m_mesh
Definition MeshUtils.hpp:240
AABBMesh m_emesh
Definition MeshUtils.hpp:241
std::vector< stl_normal > m_normals
Definition MeshUtils.hpp:242
std::vector< Vec3f > its_face_normals(const indexed_triangle_set &its)
Definition TriangleMesh.cpp:1625

References Slic3r::its_face_normals(), m_emesh, m_mesh, and m_normals.

Referenced by MeshRaycaster().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MeshRaycaster() [2/2]

Slic3r::GUI::MeshRaycaster::MeshRaycaster ( const TriangleMesh & mesh)
inlineexplicit
181 : MeshRaycaster(std::make_unique<TriangleMesh>(mesh))
182 {}
MeshRaycaster(std::shared_ptr< const TriangleMesh > mesh)
Definition MeshUtils.hpp:172

References MeshRaycaster(), and Slic3r::make_unique().

Here is the call graph for this function:

Member Function Documentation

◆ closest_hit()

bool Slic3r::GUI::MeshRaycaster::closest_hit ( const Vec2d & mouse_pos,
const Transform3d & trafo,
const Camera & camera,
Vec3f & position,
Vec3f & normal,
const ClippingPlane * clipping_plane = nullptr,
size_t * facet_idx = nullptr ) const
556{
557 Vec3d point;
558 Vec3d direction;
559 line_from_mouse_pos(mouse_pos, trafo, camera, point, direction);
560
561 const std::vector<AABBMesh::hit_result> hits = m_emesh.query_ray_hits(point, direction.normalized());
562
563 if (hits.empty())
564 return false; // no intersection found
565
566 size_t hit_id = 0;
567 if (clipping_plane != nullptr) {
568 while (hit_id < hits.size() && clipping_plane->is_point_clipped(trafo * hits[hit_id].position())) {
569 ++hit_id;
570 }
571 }
572
573 if (hit_id == hits.size())
574 return false; // all points are obscured or cut by the clipping plane.
575
576 const AABBMesh::hit_result& hit = hits[hit_id];
577
578 position = hit.position().cast<float>();
579 normal = hit.normal().cast<float>();
580
581 if (facet_idx != nullptr)
582 *facet_idx = hit.face();
583
584 return true;
585}
static void line_from_mouse_pos(const Vec2d &mouse_pos, const Transform3d &trafo, const Camera &camera, Vec3d &point, Vec3d &direction)
Definition MeshUtils.cpp:439
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
Point normal(Point pt, double scale)
Definition TreeSupport.cpp:112

References Slic3r::AABBMesh::hit_result::face(), Slic3r::GUI::ClippingPlane::is_point_clipped(), line_from_mouse_pos(), m_emesh, Slic3r::AABBMesh::hit_result::normal(), Slic3r::normal(), and Slic3r::AABBMesh::hit_result::position().

Here is the call graph for this function:

◆ get_aabb_mesh()

const AABBMesh & Slic3r::GUI::MeshRaycaster::get_aabb_mesh ( ) const
inline
200{ return m_emesh; }

References m_emesh.

◆ get_closest_facet()

int Slic3r::GUI::MeshRaycaster::get_closest_facet ( const Vec3f & point) const
601{
602 int facet_idx = 0;
603 Vec3d closest_point;
604 m_emesh.squared_distance(point.cast<double>(), facet_idx, closest_point);
605 return facet_idx;
606}

References m_emesh.

◆ get_closest_point()

Vec3f Slic3r::GUI::MeshRaycaster::get_closest_point ( const Vec3f & point,
Vec3f * normal = nullptr ) const
588{
589 int idx = 0;
590 Vec3d closest_point;
591 Vec3d pointd = point.cast<double>();
592 m_emesh.squared_distance(pointd, idx, closest_point);
593 if (normal)
594 // TODO: consider: get_normal(m_emesh, pointd).cast<float>();
595 *normal = m_normals[idx];
596
597 return closest_point.cast<float>();
598}

References m_emesh, m_normals, and Slic3r::normal().

Here is the call graph for this function:

◆ get_triangle_normal()

Vec3f Slic3r::GUI::MeshRaycaster::get_triangle_normal ( size_t facet_idx) const
435{
436 return m_normals[facet_idx];
437}

References m_normals.

◆ get_unobscured_idxs()

std::vector< unsigned > Slic3r::GUI::MeshRaycaster::get_unobscured_idxs ( const Geometry::Transformation & trafo,
const Camera & camera,
const std::vector< Vec3f > & points,
const ClippingPlane * clipping_plane = nullptr ) const
508{
509 std::vector<unsigned> out;
510
511 const Transform3d instance_matrix_no_translation_no_scaling = trafo.get_rotation_matrix();
512 Vec3d direction_to_camera = -camera.get_dir_forward();
513 Vec3d direction_to_camera_mesh = (instance_matrix_no_translation_no_scaling.inverse() * direction_to_camera).normalized().eval();
514 direction_to_camera_mesh = direction_to_camera_mesh.cwiseProduct(trafo.get_scaling_factor());
515 const Transform3d inverse_trafo = trafo.get_matrix().inverse();
516
517 for (size_t i=0; i<points.size(); ++i) {
518 const Vec3f& pt = points[i];
519 if (clipping_plane && clipping_plane->is_point_clipped(pt.cast<double>()))
520 continue;
521
522 bool is_obscured = false;
523 // Cast a ray in the direction of the camera and look for intersection with the mesh:
524 std::vector<AABBMesh::hit_result> hits;
525 // Offset the start of the ray by EPSILON to account for numerical inaccuracies.
526 hits = m_emesh.query_ray_hits((inverse_trafo * pt.cast<double>() + direction_to_camera_mesh * EPSILON),
527 direction_to_camera_mesh);
528
529 if (! hits.empty()) {
530 // If the closest hit facet normal points in the same direction as the ray,
531 // we are looking through the mesh and should therefore discard the point:
532 if (hits.front().normal().dot(direction_to_camera_mesh.cast<double>()) > 0)
533 is_obscured = true;
534
535 // Eradicate all hits that the caller wants to ignore
536 for (unsigned j=0; j<hits.size(); ++j) {
537 if (clipping_plane && clipping_plane->is_point_clipped(trafo.get_matrix() * hits[j].position())) {
538 hits.erase(hits.begin()+j);
539 --j;
540 }
541 }
542
543 // FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction.
544 // Also, the threshold is in mesh coordinates, not in actual dimensions.
545 if (! hits.empty())
546 is_obscured = true;
547 }
548 if (! is_obscured)
549 out.push_back(i);
550 }
551 return out;
552}
#define EPSILON
Definition ColorUtils.cpp:64
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65

References EPSILON, Slic3r::GUI::Camera::get_dir_forward(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_rotation_matrix(), Slic3r::Geometry::Transformation::get_scaling_factor(), Slic3r::GUI::ClippingPlane::is_point_clipped(), and m_emesh.

Here is the call graph for this function:

◆ intersects_line()

bool Slic3r::GUI::MeshRaycaster::intersects_line ( Vec3d point,
Vec3d direction,
const Transform3d & trafo ) const
493{
494 Transform3d trafo_inv = trafo.inverse();
495 Vec3d to = trafo_inv * (point + direction);
496 point = trafo_inv * point;
497 direction = (to-point).normalized();
498
499 std::vector<AABBMesh::hit_result> hits = m_emesh.query_ray_hits(point, direction);
500 std::vector<AABBMesh::hit_result> neg_hits = m_emesh.query_ray_hits(point, -direction);
501
502 return !hits.empty() || !neg_hits.empty();
503}

References m_emesh.

◆ line_from_mouse_pos()

void Slic3r::GUI::MeshRaycaster::line_from_mouse_pos ( const Vec2d & mouse_pos,
const Transform3d & trafo,
const Camera & camera,
Vec3d & point,
Vec3d & direction )
static
440{
441 CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
442 Transform3d inv = trafo.inverse();
443 point = inv*point;
444 direction = inv.linear()*direction;
445}
static void ray_from_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
Create ray(point and direction) for screen coordinate.
Definition CameraUtils.cpp:95

References Slic3r::GUI::CameraUtils::ray_from_screen_pos().

Referenced by closest_hit(), Slic3r::GUI::GLGizmoCut3D::process_cut_line(), and Slic3r::GUI::GLGizmoCut3D::unproject_on_cut_plane().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ unproject_on_mesh()

bool Slic3r::GUI::MeshRaycaster::unproject_on_mesh ( const Vec2d & mouse_pos,
const Transform3d & trafo,
const Camera & camera,
Vec3f & position,
Vec3f & normal,
const ClippingPlane * clipping_plane = nullptr,
size_t * facet_idx = nullptr,
bool sinking_limit = true ) const
450{
451 Vec3d point;
452 Vec3d direction;
453 CameraUtils::ray_from_screen_pos(camera, mouse_pos, point, direction);
454 Transform3d inv = trafo.inverse();
455 point = inv*point;
456 direction = inv.linear()*direction;
457
458 std::vector<AABBMesh::hit_result> hits = m_emesh.query_ray_hits(point, direction);
459
460 if (hits.empty())
461 return false; // no intersection found
462
463 unsigned i = 0;
464
465 // Remove points that are obscured or cut by the clipping plane.
466 // Also, remove anything below the bed (sinking objects).
467 for (i=0; i<hits.size(); ++i) {
468 Vec3d transformed_hit = trafo * hits[i].position();
469 if (transformed_hit.z() >= (sinking_limit ? SINKING_Z_THRESHOLD : -std::numeric_limits<double>::max()) &&
470 (!clipping_plane || !clipping_plane->is_point_clipped(transformed_hit)))
471 break;
472 }
473
474 if (i==hits.size() || (hits.size()-i) % 2 != 0) {
475 // All hits are either clipped, or there is an odd number of unclipped
476 // hits - meaning the nearest must be from inside the mesh.
477 return false;
478 }
479
480 // Now stuff the points in the provided vector and calculate normals if asked about them:
481 position = hits[i].position().cast<float>();
482 normal = hits[i].normal().cast<float>();
483
484 if (facet_idx)
485 *facet_idx = hits[i].face();
486
487 return true;
488}
static const float SINKING_Z_THRESHOLD
Definition Model.hpp:1967

References Slic3r::GUI::ClippingPlane::is_point_clipped(), m_emesh, Slic3r::normal(), Slic3r::GUI::CameraUtils::ray_from_screen_pos(), and Slic3r::SINKING_Z_THRESHOLD.

Here is the call graph for this function:

Member Data Documentation

◆ m_emesh

◆ m_mesh

std::shared_ptr<const TriangleMesh> Slic3r::GUI::MeshRaycaster::m_mesh
private

Referenced by MeshRaycaster().

◆ m_normals

std::vector<stl_normal> Slic3r::GUI::MeshRaycaster::m_normals
private

The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/MeshUtils.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/MeshUtils.cpp