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

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

Collaboration diagram for Slic3r::GUI::SceneRaycaster:

Classes

struct  HitResult

Public Types

enum class  EType {
  None , Bed , Volume , Gizmo ,
  FallbackGizmo
}
enum class  EIdBase { Bed = 0 , Volume = 1000 , Gizmo = 1000000 , FallbackGizmo = 2000000 }
enum class  EHitMode : unsigned char { Picking , SceneOnly , VolumesOnly }

Public Member Functions

 SceneRaycaster ()
std::shared_ptr< SceneRaycasterItem > add_raycaster (EType type, int picking_id, const MeshRaycaster &raycaster, const Transform3d &trafo, bool use_back_faces=false)
void remove_raycasters (EType type, int id)
void remove_raycasters (EType type)
void remove_raycaster (std::shared_ptr< SceneRaycasterItem > item)
std::vector< std::shared_ptr< SceneRaycasterItem > > * get_raycasters (EType type)
const std::vector< std::shared_ptr< SceneRaycasterItem > > * get_raycasters (EType type) const
void set_gizmos_on_top (bool value)
HitResult hit (const Vec2d &mouse_pos, const Camera &camera, const ClippingPlane *clipping_plane=nullptr, EHitMode mode=EHitMode::Picking) const

Static Public Member Functions

static int decode_id (EType type, int id)

Static Private Member Functions

static int encode_id (EType type, int id)
static int base_id (EType type)

Private Attributes

std::vector< std::shared_ptr< SceneRaycasterItem > > m_bed
std::vector< std::shared_ptr< SceneRaycasterItem > > m_volumes
std::vector< std::shared_ptr< SceneRaycasterItem > > m_gizmos
std::vector< std::shared_ptr< SceneRaycasterItem > > m_fallback_gizmos
bool m_gizmos_on_top { false }

Detailed Description

Member Enumeration Documentation

◆ EHitMode

enum class Slic3r::GUI::SceneRaycaster::EHitMode : unsigned char
strong
Enumerator
Picking 
SceneOnly 
VolumesOnly 
66 {
67 Picking,
68 SceneOnly,
69 VolumesOnly // Navigation when the bed is hidden.
70 };

◆ EIdBase

Enumerator
Bed 
Volume 
Gizmo 
FallbackGizmo 
56 {
57 Bed = 0,
58 Volume = 1000, // Must be greater than PartPlateList::MAX_PLATES_COUNT * PartPlate::GRABBER_COUNT
59 Gizmo = 1000000,
60 FallbackGizmo = 2000000
61 };

◆ EType

Enumerator
None 
Bed 
Volume 
Gizmo 
FallbackGizmo 
47 {
48 None,
49 Bed,
50 Volume,
51 Gizmo,
52 FallbackGizmo // Is used for gizmo grabbers which will be hit after all grabbers of Gizmo type
53 };
@ None
Definition SketchEngine.hpp:180

Constructor & Destructor Documentation

◆ SceneRaycaster()

Slic3r::GUI::SceneRaycaster::SceneRaycaster ( )
24 {
25#if ENABLE_RAYCAST_PICKING_DEBUG
26 // hit point
27 m_sphere.init_from(its_make_sphere(1.0, double(PI) / 16.0));
28 m_sphere.set_color(ColorRGBA::YELLOW());
29
30 // hit normal
31 GLModel::Geometry init_data;
33 init_data.color = ColorRGBA::YELLOW();
34 init_data.reserve_vertices(2);
35 init_data.reserve_indices(2);
36
37 // vertices
38 init_data.add_vertex((Vec3f)Vec3f::Zero());
39 init_data.add_vertex((Vec3f)Vec3f::UnitZ());
40
41 // indices
42 init_data.add_line(0, 1);
43
44 m_line.init_from(std::move(init_data));
45#endif // ENABLE_RAYCAST_PICKING_DEBUG
46}
static const ColorRGBA YELLOW()
Definition Color.hpp:141
static constexpr double PI
Definition libslic3r.h:81
indexed_triangle_set its_make_sphere(double radius, double fa)
Definition TriangleMesh.cpp:1128
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65

References Slic3r::GUI::GLModel::Geometry::add_line(), Slic3r::GUI::GLModel::Geometry::add_vertex(), Slic3r::GUI::GLModel::Geometry::color, Slic3r::GUI::GLModel::Geometry::format, Slic3r::its_make_sphere(), Slic3r::GUI::GLModel::Geometry::Lines, Slic3r::GUI::GLModel::Geometry::P3, PI, Slic3r::GUI::GLModel::Geometry::reserve_indices(), Slic3r::GUI::GLModel::Geometry::reserve_vertices(), and Slic3r::ColorRGBA::YELLOW().

Here is the call graph for this function:

Member Function Documentation

◆ add_raycaster()

std::shared_ptr< SceneRaycasterItem > Slic3r::GUI::SceneRaycaster::add_raycaster ( EType type,
int picking_id,
const MeshRaycaster & raycaster,
const Transform3d & trafo,
bool use_back_faces = false )
50{
51 switch (type) {
52 case EType::Bed: { return m_bed.emplace_back(std::make_shared<SceneRaycasterItem>(encode_id(type, id), raycaster, trafo, use_back_faces)); }
53 case EType::Volume: { return m_volumes.emplace_back(std::make_shared<SceneRaycasterItem>(encode_id(type, id), raycaster, trafo, use_back_faces)); }
54 case EType::Gizmo: { return m_gizmos.emplace_back(std::make_shared<SceneRaycasterItem>(encode_id(type, id), raycaster, trafo, use_back_faces)); }
55 case EType::FallbackGizmo: { return m_fallback_gizmos.emplace_back(std::make_shared<SceneRaycasterItem>(encode_id(type, id), raycaster, trafo, use_back_faces)); }
56 default: { assert(false); return nullptr; }
57 };
58}
static int encode_id(EType type, int id)
Definition SceneRaycaster.cpp:343
std::vector< std::shared_ptr< SceneRaycasterItem > > m_fallback_gizmos
Definition SceneRaycaster.hpp:86
std::vector< std::shared_ptr< SceneRaycasterItem > > m_gizmos
Definition SceneRaycaster.hpp:85
std::vector< std::shared_ptr< SceneRaycasterItem > > m_bed
Definition SceneRaycaster.hpp:83
std::vector< std::shared_ptr< SceneRaycasterItem > > m_volumes
Definition SceneRaycaster.hpp:84
@ FallbackGizmo
Definition SceneRaycaster.hpp:52
@ Gizmo
Definition SceneRaycaster.hpp:51
@ Volume
Definition SceneRaycaster.hpp:50
@ Bed
Definition SceneRaycaster.hpp:49

References Bed, encode_id(), FallbackGizmo, Gizmo, m_bed, m_fallback_gizmos, m_gizmos, m_volumes, and Volume.

Here is the call graph for this function:

◆ base_id()

int Slic3r::GUI::SceneRaycaster::base_id ( EType type)
staticprivate
329{
330 switch (type)
331 {
332 case EType::Bed: { return int(EIdBase::Bed); }
333 case EType::Volume: { return int(EIdBase::Volume); }
334 case EType::Gizmo: { return int(EIdBase::Gizmo); }
335 case EType::FallbackGizmo: { return int(EIdBase::FallbackGizmo); }
336 default: { break; }
337 };
338
339 assert(false);
340 return -1;
341}
@ FallbackGizmo
Definition SceneRaycaster.hpp:60
@ Gizmo
Definition SceneRaycaster.hpp:59
@ Volume
Definition SceneRaycaster.hpp:58
@ Bed
Definition SceneRaycaster.hpp:57

References Bed, FallbackGizmo, Gizmo, and Volume.

Referenced by decode_id(), and encode_id().

Here is the caller graph for this function:

◆ decode_id()

int Slic3r::GUI::SceneRaycaster::decode_id ( EType type,
int id )
static
344{ return id - base_id(type); }
static int base_id(EType type)
Definition SceneRaycaster.cpp:328

References base_id().

Referenced by Slic3r::GUI::GLCanvas3D::_picking_pass(), Slic3r::GUI::GLCanvas3D::_update_inactive_plates_visibility(), Slic3r::GUI::create_meshes(), and hit().

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

◆ encode_id()

int Slic3r::GUI::SceneRaycaster::encode_id ( EType type,
int id )
staticprivate
343{ return base_id(type) + id; }

References base_id().

Referenced by add_raycaster(), and remove_raycasters().

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

◆ get_raycasters() [1/2]

std::vector< std::shared_ptr< SceneRaycasterItem > > * Slic3r::GUI::SceneRaycaster::get_raycasters ( EType type)
299{
300 std::vector<std::shared_ptr<SceneRaycasterItem>>* ret = nullptr;
301 switch (type)
302 {
303 case EType::Bed: { ret = &m_bed; break; }
304 case EType::Volume: { ret = &m_volumes; break; }
305 case EType::Gizmo: { ret = &m_gizmos; break; }
306 case EType::FallbackGizmo: { ret = &m_fallback_gizmos; break; }
307 default: { break; }
308 }
309 assert(ret != nullptr);
310 return ret;
311}

References Bed, FallbackGizmo, Gizmo, m_bed, m_fallback_gizmos, m_gizmos, m_volumes, and Volume.

Referenced by hit(), and remove_raycasters().

Here is the caller graph for this function:

◆ get_raycasters() [2/2]

const std::vector< std::shared_ptr< SceneRaycasterItem > > * Slic3r::GUI::SceneRaycaster::get_raycasters ( EType type) const
314{
315 const std::vector<std::shared_ptr<SceneRaycasterItem>>* ret = nullptr;
316 switch (type)
317 {
318 case EType::Bed: { ret = &m_bed; break; }
319 case EType::Volume: { ret = &m_volumes; break; }
320 case EType::Gizmo: { ret = &m_gizmos; break; }
321 case EType::FallbackGizmo: { ret = &m_fallback_gizmos; break; }
322 default: { break; }
323 }
324 assert(ret != nullptr);
325 return ret;
326}

References Bed, FallbackGizmo, Gizmo, m_bed, m_fallback_gizmos, m_gizmos, m_volumes, and Volume.

◆ hit()

SceneRaycaster::HitResult Slic3r::GUI::SceneRaycaster::hit ( const Vec2d & mouse_pos,
const Camera & camera,
const ClippingPlane * clipping_plane = nullptr,
SceneRaycaster::EHitMode mode = EHitMode::Picking ) const
113{
114 // Orca: Picking may favor an already selected volume for interaction, while camera
115 // navigation must always use the geometrically closest visible scene surface.
116 // helper class used to return currently selected volume as hit when overlapping with other volumes
117 // to allow the user to click and drag on a selected volume
118 class VolumeKeeper
119 {
120 std::optional<unsigned int> m_selected_volume_id;
121 Vec3f m_closest_hit_pos{ std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
122 bool m_selected_volume_already_found{ false };
123
124 public:
125 explicit VolumeKeeper(bool enabled) {
126 // Orca: Disable selected-volume bias for navigation raycasts.
127 if (!enabled)
128 return;
129
130 const Selection& selection = wxGetApp().plater()->get_selection();
131 if (selection.is_single_volume() || selection.is_single_modifier()) {
132 const GLVolume* volume = selection.get_first_volume();
133 if (!volume->is_wipe_tower && !volume->is_sla_pad() && !volume->is_sla_support())
134 m_selected_volume_id = *selection.get_volume_idxs().begin();
135 }
136 }
137
138 bool is_active() const { return m_selected_volume_id.has_value(); }
139 const Vec3f& get_closest_hit_pos() const { return m_closest_hit_pos; }
140 bool check_hit_result(const HitResult& hit) {
141 assert(is_active());
142
143 if (m_selected_volume_already_found && hit.type == SceneRaycaster::EType::Volume && hit.position.isApprox(m_closest_hit_pos))
144 return false;
145
146 if (hit.type == SceneRaycaster::EType::Volume)
147 m_selected_volume_already_found = *m_selected_volume_id == (unsigned int)decode_id(hit.type, hit.raycaster_id);
148
149 m_closest_hit_pos = hit.position;
150 return true;
151 }
152 };
153
154 VolumeKeeper volume_keeper(mode == EHitMode::Picking);
155
156 double closest_hit_squared_distance = std::numeric_limits<double>::max();
157 auto is_closest = [&closest_hit_squared_distance, &volume_keeper](const Camera& camera, const Vec3f& hit) {
158 const double hit_squared_distance = (camera.get_position() - hit.cast<double>()).squaredNorm();
159 bool ret = hit_squared_distance < closest_hit_squared_distance;
160 if (volume_keeper.is_active())
161 ret |= hit.isApprox(volume_keeper.get_closest_hit_pos());
162 if (ret)
163 closest_hit_squared_distance = hit_squared_distance;
164 return ret;
165 };
166
167#if ENABLE_RAYCAST_PICKING_DEBUG
168 const_cast<std::optional<HitResult>*>(&m_last_hit)->reset();
169#endif // ENABLE_RAYCAST_PICKING_DEBUG
170
171 HitResult ret;
172
173 auto test_raycasters = [this, is_closest, clipping_plane, mode, &volume_keeper](EType type, const Vec2d& mouse_pos, const Camera& camera, HitResult& ret) {
174 const ClippingPlane* clip_plane = (clipping_plane != nullptr && type == EType::Volume) ? clipping_plane : nullptr;
175 const std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters(type);
176 const Vec3f camera_forward = camera.get_dir_forward().cast<float>();
177 HitResult current_hit = { type };
178 for (std::shared_ptr<SceneRaycasterItem> item : *raycasters) {
179 if (!item->is_active())
180 continue;
181
182 // Each plate's component 0 is its surface; the remaining Bed IDs are controls.
183 // Keep controls clickable, but do not use them as camera-pan anchors.
184 if (mode != EHitMode::Picking && type == EType::Bed &&
185 decode_id(type, item->get_id()) % PartPlate::GRABBER_COUNT != 0)
186 continue;
187
188 current_hit.raycaster_id = item->get_id();
189 const Transform3d& trafo = item->get_transform();
190 if (item->get_raycaster()->closest_hit(mouse_pos, trafo, camera, current_hit.position, current_hit.normal, clip_plane)) {
191 current_hit.position = (trafo * current_hit.position.cast<double>()).cast<float>();
192 current_hit.normal = (trafo.matrix().block(0, 0, 3, 3).inverse().transpose() * current_hit.normal.cast<double>()).normalized().cast<float>();
193 // Orca: Perspective rays away from the viewport center are not parallel to camera_forward.
194 // Keep picking's legacy policy, but accept every front-facing navigation surface.
195 const Vec3f view_direction = mode != EHitMode::Picking && camera.get_type() == Camera::EType::Perspective ?
196 Vec3f((current_hit.position.cast<double>() - camera.get_position()).cast<float>()) : camera_forward;
197 if (item->use_back_faces() || current_hit.normal.dot(view_direction) < 0.0f) {
198 if (is_closest(camera, current_hit.position)) {
199 if (volume_keeper.is_active()) {
200 if (volume_keeper.check_hit_result(current_hit))
201 ret = current_hit;
202 }
203 else
204 ret = current_hit;
205 }
206 }
207 }
208 }
209 };
210
211 // Orca: Gizmo geometry is an interaction target, not a valid depth anchor for camera movement.
212 if (mode == EHitMode::Picking) {
213 if (!m_gizmos.empty())
214 test_raycasters(EType::Gizmo, mouse_pos, camera, ret);
215
216 if (!m_fallback_gizmos.empty() && !ret.is_valid())
217 test_raycasters(EType::FallbackGizmo, mouse_pos, camera, ret);
218 }
219
220 if (!m_gizmos_on_top || !ret.is_valid()) {
221 // Orca: In perspective the bottom of the viewport can see the bed even at a horizontal view.
222 if ((mode == EHitMode::SceneOnly || (mode == EHitMode::Picking && camera.is_looking_downward())) && !m_bed.empty())
223 test_raycasters(EType::Bed, mouse_pos, camera, ret);
224 if (!m_volumes.empty())
225 test_raycasters(EType::Volume, mouse_pos, camera, ret);
226 }
227
228 if (ret.is_valid())
229 ret.raycaster_id = decode_id(ret.type, ret.raycaster_id);
230
231#if ENABLE_RAYCAST_PICKING_DEBUG
232 *const_cast<std::optional<HitResult>*>(&m_last_hit) = ret;
233#endif // ENABLE_RAYCAST_PICKING_DEBUG
234 return ret;
235}
static constexpr unsigned int GRABBER_COUNT
Definition PartPlate.hpp:288
@ SceneOnly
Definition SceneRaycaster.hpp:68
@ Picking
Definition SceneRaycaster.hpp:67
HitResult hit(const Vec2d &mouse_pos, const Camera &camera, const ClippingPlane *clipping_plane=nullptr, EHitMode mode=EHitMode::Picking) const
Definition SceneRaycaster.cpp:111
static int decode_id(EType type, int id)
Definition SceneRaycaster.cpp:344
std::vector< std::shared_ptr< SceneRaycasterItem > > * get_raycasters(EType type)
Definition SceneRaycaster.cpp:298
EType
Definition SceneRaycaster.hpp:47
bool m_gizmos_on_top
Definition SceneRaycaster.hpp:90
@ Selection
Definition Shortcuts.hpp:72
@ Camera
Definition Shortcuts.hpp:72
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299
bool is_active(id view)
Definition MacIME.mm:26
@ Perspective
Definition Camera.hpp:40
Definition SceneRaycaster.hpp:73
int raycaster_id
Definition SceneRaycaster.hpp:75

References Bed, Slic3r::cast(), decode_id(), FallbackGizmo, Slic3r::GUI::Camera::get_dir_forward(), Slic3r::GUI::Selection::get_first_volume(), Slic3r::GUI::Camera::get_position(), get_raycasters(), Slic3r::GUI::Camera::get_type(), Slic3r::GUI::Selection::get_volume_idxs(), Gizmo, Slic3r::GUI::PartPlate::GRABBER_COUNT, hit(), Slic3r::GUI::Camera::is_looking_downward(), Slic3r::GUI::Selection::is_single_modifier(), Slic3r::GUI::Selection::is_single_volume(), Slic3r::GLVolume::is_sla_pad(), Slic3r::GLVolume::is_sla_support(), Slic3r::GUI::SceneRaycaster::HitResult::is_valid(), m_bed, m_fallback_gizmos, m_gizmos, m_gizmos_on_top, m_volumes, Slic3r::GUI::Camera::Perspective, Picking, Slic3r::GUI::SceneRaycaster::HitResult::raycaster_id, SceneOnly, Slic3r::GUI::SceneRaycaster::HitResult::type, and Volume.

Referenced by hit().

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

◆ remove_raycaster()

void Slic3r::GUI::SceneRaycaster::remove_raycaster ( std::shared_ptr< SceneRaycasterItem > item)
84{
85 for (auto it = m_bed.begin(); it != m_bed.end(); ++it) {
86 if (*it == item) {
87 m_bed.erase(it);
88 return;
89 }
90 }
91 for (auto it = m_volumes.begin(); it != m_volumes.end(); ++it) {
92 if (*it == item) {
93 m_volumes.erase(it);
94 return;
95 }
96 }
97 for (auto it = m_gizmos.begin(); it != m_gizmos.end(); ++it) {
98 if (*it == item) {
99 m_gizmos.erase(it);
100 return;
101 }
102 }
103 for (auto it = m_fallback_gizmos.begin(); it != m_fallback_gizmos.end(); ++it) {
104 if (*it == item) {
105 m_fallback_gizmos.erase(it);
106 return;
107 }
108 }
109}

References m_bed, m_fallback_gizmos, m_gizmos, and m_volumes.

◆ remove_raycasters() [1/2]

void Slic3r::GUI::SceneRaycaster::remove_raycasters ( EType type)
73{
74 switch (type) {
75 case EType::Bed: { m_bed.clear(); break; }
76 case EType::Volume: { m_volumes.clear(); break; }
77 case EType::Gizmo: { m_gizmos.clear(); break; }
78 case EType::FallbackGizmo: { m_fallback_gizmos.clear(); break; }
79 default: { break; }
80 };
81}

References Bed, FallbackGizmo, Gizmo, m_bed, m_fallback_gizmos, m_gizmos, m_volumes, and Volume.

◆ remove_raycasters() [2/2]

void Slic3r::GUI::SceneRaycaster::remove_raycasters ( EType type,
int id )
61{
62 std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters(type);
63 auto it = raycasters->begin();
64 while (it != raycasters->end()) {
65 if ((*it)->get_id() == encode_id(type, id))
66 it = raycasters->erase(it);
67 else
68 ++it;
69 }
70}

References encode_id(), and get_raycasters().

Here is the call graph for this function:

◆ set_gizmos_on_top()

void Slic3r::GUI::SceneRaycaster::set_gizmos_on_top ( bool value)
inline
110{ m_gizmos_on_top = value; }

References m_gizmos_on_top.

Member Data Documentation

◆ m_bed

std::vector<std::shared_ptr<SceneRaycasterItem> > Slic3r::GUI::SceneRaycaster::m_bed
private

◆ m_fallback_gizmos

std::vector<std::shared_ptr<SceneRaycasterItem> > Slic3r::GUI::SceneRaycaster::m_fallback_gizmos
private

◆ m_gizmos

std::vector<std::shared_ptr<SceneRaycasterItem> > Slic3r::GUI::SceneRaycaster::m_gizmos
private

◆ m_gizmos_on_top

bool Slic3r::GUI::SceneRaycaster::m_gizmos_on_top { false }
private
90{ false };

Referenced by hit(), and set_gizmos_on_top().

◆ m_volumes

std::vector<std::shared_ptr<SceneRaycasterItem> > Slic3r::GUI::SceneRaycaster::m_volumes
private

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