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

Cast rays from camera to scene Used for find hit point on model volume under mouse cursor. More...

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/Utils/RaycastManager.hpp>

Collaboration diagram for Slic3r::GUI::RaycastManager:

Classes

class  ISkip
 Interface for identify allowed volumes to cast rays. More...
struct  SurfacePoint
struct  Hit
struct  ClosePoint
class  SkipVolume
class  AllowVolumes

Public Types

using Mesh = std::pair<size_t, std::unique_ptr<AABBMesh> >
using Meshes = std::vector<Mesh>
using TrKey = std::pair<size_t, size_t>
using TrItem = std::pair<TrKey, Transform3d>
using TrItems = std::vector<TrItem>

Public Member Functions

void actualize (const ModelObject &object, const ISkip *skip=nullptr, Meshes *meshes=nullptr)
 Actualize raycasters + transformation Detection of removed object Detection of removed instance Detection of removed volume.
void actualize (const ModelInstance &instance, const ISkip *skip=nullptr, Meshes *meshes=nullptr)
std::optional< Hit > first_hit (const Vec3d &point, const Vec3d &direction, const ISkip *skip=nullptr) const
 Unproject on mesh and return closest hit to point in given direction.
std::optional< Hit > closest_hit (const Vec3d &point, const Vec3d &direction, const ISkip *skip=nullptr) const
 Unproject Ray(point direction) on mesh to find closest hit of surface in given direction NOTE: It inspect also oposit direction of ray !!
std::optional< ClosePoint > closest (const Vec3d &point, const ISkip *skip=nullptr) const
 Search of closest point.
Transform3d get_transformation (const TrKey &tr_key) const
 Getter on transformation from hitted volume to world.

Private Attributes

Meshes m_meshes
TrItems m_transformations

Detailed Description

Cast rays from camera to scene Used for find hit point on model volume under mouse cursor.


Class Documentation

◆ Slic3r::GUI::RaycastManager::SurfacePoint

struct Slic3r::GUI::RaycastManager::SurfacePoint
template<typename T>
struct Slic3r::GUI::RaycastManager::SurfacePoint< T >
Inheritance diagram for Slic3r::GUI::RaycastManager::SurfacePoint< T >:
Class Members
typedef Matrix< T, 3, 1, DontAlign > Vec3 Eigen::Matrix<T, 3, 1, Eigen::DontAlign>
Class Members
Vec3 normal = Vec3::UnitZ()
Vec3 position = Vec3::Zero()

◆ Slic3r::GUI::RaycastManager::ClosePoint

struct Slic3r::GUI::RaycastManager::ClosePoint
Collaboration diagram for Slic3r::GUI::RaycastManager::ClosePoint:
Class Members
Vec3d point
double squared_distance
TrKey tr_key

Member Typedef Documentation

◆ Mesh

using Slic3r::GUI::RaycastManager::Mesh = std::pair<size_t, std::unique_ptr<AABBMesh> >

◆ Meshes

◆ TrItem

◆ TrItems

◆ TrKey

using Slic3r::GUI::RaycastManager::TrKey = std::pair<size_t, size_t>

Member Function Documentation

◆ actualize() [1/2]

void RaycastManager::actualize ( const ModelInstance & instance,
const ISkip * skip = nullptr,
Meshes * meshes = nullptr )
77{
78 const ModelVolumePtrs &volumes = instance.get_object()->volumes;
79
80 // actualize MeshRaycaster
81 ::actualize(m_meshes, volumes, skip, meshes);
82
83 // check if inscance was removed
84 std::vector<bool> removed_transf(m_transformations.size(), {true});
85
86 bool need_sort = false;
87 // actualize transformation matrices
88 for (const ModelVolume *volume : volumes) {
89 if (skip != nullptr && skip->skip(volume->id().id))
90 continue;
91 const Transform3d &volume_tr = volume->get_matrix();
92 const Transform3d &instrance_tr = instance.get_matrix();
93 Transform3d transformation = instrance_tr * volume_tr;
94 TrKey key = ::create_key(*volume, instance);
95 auto item = ::find(m_transformations, key);
96 if (item != m_transformations.end()) {
97 // actualize transformation all the time
98 item->second = transformation;
99 size_t index = item - m_transformations.begin();
100 removed_transf[index] = false;
101 } else {
102 // add new transformation
103 m_transformations.emplace_back(key, transformation);
104 need_sort = true;
105 }
106 }
107
108 // clean other transformation
109 ::erase(m_transformations, removed_transf);
110
111 if (need_sort)
112 std::sort(m_transformations.begin(), m_transformations.end(), ::is_lower);
113}
void actualize(const ModelObject &object, const ISkip *skip=nullptr, Meshes *meshes=nullptr)
Actualize raycasters + transformation Detection of removed object Detection of removed instance Detec...
Definition RaycastManager.cpp:38
Meshes m_meshes
Definition RaycastManager.hpp:77
std::pair< size_t, size_t > TrKey
Definition RaycastManager.hpp:33
TrItems m_transformations
Definition RaycastManager.hpp:80
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
std::vector< ModelVolume * > ModelVolumePtrs
Definition Model.hpp:139

References actualize(), Slic3r::ModelInstance::get_matrix(), Slic3r::ModelInstance::get_object(), m_meshes, m_transformations, Slic3r::GUI::RaycastManager::ISkip::skip(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ actualize() [2/2]

void RaycastManager::actualize ( const ModelObject & object,
const ISkip * skip = nullptr,
Meshes * meshes = nullptr )

Actualize raycasters + transformation Detection of removed object Detection of removed instance Detection of removed volume.

Parameters
objectModel representation
skipCondifiton for skip actualization
meshesSpeed up for already created AABBtrees
39{
40 // actualize MeshRaycaster
41 ::actualize(m_meshes, object.volumes, skip, meshes);
42
43 // check if inscance was removed
44 std::vector<bool> removed_transf(m_transformations.size(), {true});
45
46 bool need_sort = false;
47 // actualize transformation matrices
48 for (const ModelVolume *volume : object.volumes) {
49 if (skip != nullptr && skip->skip(volume->id().id)) continue;
50 const Transform3d &volume_tr = volume->get_matrix();
51 for (const ModelInstance *instance : object.instances) {
52 const Transform3d &instrance_tr = instance->get_matrix();
53 Transform3d transformation = instrance_tr * volume_tr;
54 TrKey key = ::create_key(*volume, *instance);
55 auto item = ::find(m_transformations, key);
56 if (item != m_transformations.end()) {
57 // actualize transformation all the time
58 item->second = transformation;
59 size_t index = item - m_transformations.begin();
60 removed_transf[index] = false;
61 } else {
62 // add new transformation
63 m_transformations.emplace_back(key, transformation);
64 need_sort = true;
65 }
66 }
67 }
68
69 // clean other transformation
70 ::erase(m_transformations, removed_transf);
71
72 if (need_sort)
73 std::sort(m_transformations.begin(), m_transformations.end(), ::is_lower);
74}

References actualize(), m_meshes, m_transformations, and Slic3r::GUI::RaycastManager::ISkip::skip().

Referenced by actualize(), actualize(), Slic3r::GUI::calc_distance(), Slic3r::GUI::calc_surface_offset(), anonymous_namespace{EmbossJob.cpp}::start_create_volume_on_surface_job(), and anonymous_namespace{SurfaceDrag.cpp}::start_dragging().

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

◆ closest()

std::optional< RaycastManager::ClosePoint > RaycastManager::closest ( const Vec3d & point,
const ISkip * skip = nullptr ) const

Search of closest point.

Parameters
pointPoint
skipDefine which caster will be skipped, null mean no skip
Returns
210{
211 std::optional<ClosePoint> closest;
212 for (const auto &[key, transformation] : m_transformations) {
213 size_t volume_id = key.second;
214 if (skip != nullptr && skip->skip(volume_id))
215 continue;
216 const AABBMesh *mesh = ::get_mesh(m_meshes, volume_id);
217 if (mesh == nullptr) continue;
218 Transform3d tr_inv = transformation.inverse();
219 Vec3d mesh_point = tr_inv * point;
220
221 int face_idx = 0;
222 Vec3d closest_point;
223 Vec3d pointd = point.cast<double>();
224 mesh->squared_distance(pointd, face_idx, closest_point);
225
226 double squared_distance = (mesh_point - closest_point).squaredNorm();
227 if (closest.has_value() && closest->squared_distance < squared_distance)
228 continue;
229
230 closest = ClosePoint{key, closest_point, squared_distance};
231 }
232 return closest;
233}
std::optional< ClosePoint > closest(const Vec3d &point, const ISkip *skip=nullptr) const
Search of closest point.
Definition RaycastManager.cpp:209
Definition RaycastManager.hpp:67
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68

References closest(), m_meshes, m_transformations, Slic3r::GUI::RaycastManager::ISkip::skip(), and Slic3r::AABBMesh::squared_distance().

Referenced by Slic3r::GUI::calc_surface_offset(), closest(), and closest_hit().

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

◆ closest_hit()

std::optional< RaycastManager::Hit > RaycastManager::closest_hit ( const Vec3d & point,
const Vec3d & direction,
const ISkip * skip = nullptr ) const

Unproject Ray(point direction) on mesh to find closest hit of surface in given direction NOTE: It inspect also oposit direction of ray !!

Parameters
pointStart point for ray
directionDirection of ray, orientation doesn't matter, both are used
skipDefine which caster will be skipped, null mean no skip
Returns
Position on surface, normal direction and transformation key, which define hitted object instance
178{
179 std::optional<Hit> closest;
180 for (const auto &[key, transformation] : m_transformations) {
181 size_t volume_id = key.second;
182 if (skip != nullptr && skip->skip(volume_id)) continue;
183 const AABBMesh *mesh = ::get_mesh(m_meshes, volume_id);
184 if (mesh == nullptr) continue;
185 Transform3d tr_inv = transformation.inverse();
186 Vec3d mesh_point = tr_inv * point;
187 Vec3d mesh_direction = tr_inv.linear() * direction;
188
189 // Need for detect that actual point position is on correct place
190 Vec3d point_positive = mesh_point - mesh_direction;
191 Vec3d point_negative = mesh_point + mesh_direction;
192
193 // Throw ray to both directions of ray
194 std::vector<AABBMesh::hit_result> hits = mesh->query_ray_hits(point_positive, mesh_direction);
195 std::vector<AABBMesh::hit_result> hits_neg = mesh->query_ray_hits(point_negative, -mesh_direction);
196 hits.insert(hits.end(), std::make_move_iterator(hits_neg.begin()), std::make_move_iterator(hits_neg.end()));
197 for (const AABBMesh::hit_result &hit : hits) {
198 Vec3d diff = mesh_point - hit.position();
199 double squared_distance = diff.squaredNorm();
200 if (closest.has_value() &&
201 closest->squared_distance < squared_distance)
202 continue;
203 closest = Hit{{hit.position(), hit.normal()}, key, squared_distance};
204 }
205 }
206 return closest;
207}
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:731
Definition RaycastManager.hpp:61

References closest(), Slic3r::diff(), m_meshes, m_transformations, Slic3r::AABBMesh::query_ray_hits(), and Slic3r::GUI::RaycastManager::ISkip::skip().

Referenced by Slic3r::GUI::calc_distance(), and Slic3r::GUI::calc_surface_offset().

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

◆ first_hit()

std::optional< RaycastManager::Hit > RaycastManager::first_hit ( const Vec3d & point,
const Vec3d & direction,
const ISkip * skip = nullptr ) const

Unproject on mesh and return closest hit to point in given direction.

Parameters
pointPosition in space
directionCasted ray direction
skipDefine which caster will be skipped, null mean no skip
Returns
Position on surface, normal direction in world coorinate
  • key, to know hitted instance and volume
116{
117 // Improve: it is not neccessaru to use AABBMesh and calc normal for every hit
118
119 // Results
120 const AABBMesh *hit_mesh = nullptr;
121 double hit_squared_distance = 0.;
122 int hit_face = -1;
123 Vec3d hit_world { Vec3d::Zero() };
124 const Transform3d *hit_tramsformation = nullptr;
125 const TrKey *hit_key = nullptr;
126
127 for (const auto &[key, transformation]: m_transformations) {
128 size_t volume_id = key.second;
129 if (skip != nullptr && skip->skip(volume_id)) continue;
130 const AABBMesh *mesh = ::get_mesh(m_meshes, volume_id);
131 if (mesh == nullptr) continue;
132 Transform3d inv = transformation.inverse();
133
134 // transform input into mesh world
135 Vec3d point_ = inv * point;
136 Vec3d direction_= inv.linear() * direction;
137
138 std::vector<AABBMesh::hit_result> hits = mesh->query_ray_hits(point_, direction_);
139 if (hits.empty()) continue; // no intersection found
140
141 const AABBMesh::hit_result &hit = hits.front();
142
143 // convert to world
144 Vec3d world = transformation * hit.position();
145 double squared_distance = (point - world).squaredNorm();
146 if (hit_mesh != nullptr &&
147 hit_squared_distance < squared_distance)
148 continue; // exist closer one
149
150 hit_mesh = mesh;
151 hit_squared_distance = squared_distance;
152 hit_face = hit.face();
153 hit_world = world;
154 hit_tramsformation = &transformation;
155 hit_key = &key;
156 }
157
158 if (hit_mesh == nullptr)
159 return {};
160
161 // Calculate normal from transformed triangle
162 // NOTE: Anisotropic transformation of normal is not perpendiculat to triangle
163 const Vec3i32 tri = hit_mesh->indices(hit_face);
164 std::array<Vec3d,3> pts;
165 auto tr = hit_tramsformation->linear().eval();
166 for (int i = 0; i < 3; ++i)
167 pts[i] = tr * hit_mesh->vertices(tri[i]).cast<double>();
168 Vec3d normal_world = (pts[1] - pts[0]).cross(pts[2] - pts[1]);
169 if (has_reflection(*hit_tramsformation))
170 normal_world *= -1;
171 normal_world.normalize();
172
173 SurfacePoint<double> point_world{hit_world, normal_world};
174 return RaycastManager::Hit{point_world, *hit_key, hit_squared_distance};
175}
Definition RaycastManager.hpp:54
T cross(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:168
bool has_reflection(const Transform3d &transform)
Check whether transformation matrix contains odd number of mirroring. NOTE: In code is sometime funct...
Definition Point.hpp:179
Eigen::Matrix< int32_t, 3, 1, Eigen::DontAlign > Vec3i32
Definition Point.hpp:59

References Slic3r::cross(), Slic3r::AABBMesh::hit_result::face(), Slic3r::has_reflection(), Slic3r::AABBMesh::indices(), m_meshes, m_transformations, Slic3r::AABBMesh::hit_result::position(), Slic3r::AABBMesh::query_ray_hits(), Slic3r::GUI::RaycastManager::ISkip::skip(), and Slic3r::AABBMesh::vertices().

Referenced by Slic3r::GUI::ray_from_camera().

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

◆ get_transformation()

Slic3r::Transform3d RaycastManager::get_transformation ( const TrKey & tr_key) const

Getter on transformation from hitted volume to world.

Parameters
tr_keyDefine transformation
Returns
Transformation for key
235 {
236 auto tr = ::find(m_transformations, tr_key);
237 if (tr == m_transformations.end())
238 return Transform3d::Identity();
239 return tr->second;
240}

References m_transformations.

Referenced by Slic3r::GUI::calc_distance(), and Slic3r::GUI::calc_surface_offset().

Here is the caller graph for this function:

Member Data Documentation

◆ m_meshes

Meshes Slic3r::GUI::RaycastManager::m_meshes
private

◆ m_transformations

TrItems Slic3r::GUI::RaycastManager::m_transformations
private

The documentation for this class was generated from the following files: