113{
114
115
116
117
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
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) {
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
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
170
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>();
178 for (std::shared_ptr<SceneRaycasterItem> item : *raycasters) {
179 if (!item->is_active())
180 continue;
181
182
183
186 continue;
187
188 current_hit.raycaster_id = item->get_id();
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
194
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
215
218 }
219
221
223 test_raycasters(
EType::Bed, mouse_pos, camera, ret);
226 }
227
228 if (ret.is_valid())
230
231#if ENABLE_RAYCAST_PICKING_DEBUG
232 *const_cast<std::optional<HitResult>*>(&m_last_hit) = ret;
233#endif
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