diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 8f4efffd8..a9ba067d4 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -659,8 +659,9 @@ public: void post_event(wxEvent &&event); #if ENABLE_RAYCAST_PICKING - std::shared_ptr add_raycaster_for_picking(SceneRaycaster::EType type, int id, const MeshRaycaster& raycaster, const Transform3d& trafo) { - return m_scene_raycaster.add_raycaster(type, id, raycaster, trafo); + std::shared_ptr add_raycaster_for_picking(SceneRaycaster::EType type, int id, const MeshRaycaster& raycaster, + const Transform3d& trafo, bool use_back_faces = false) { + return m_scene_raycaster.add_raycaster(type, id, raycaster, trafo, use_back_faces); } void remove_raycasters_for_picking(SceneRaycaster::EType type, int id) { m_scene_raycaster.remove_raycasters(type, id); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 23889c9d7..6b8f3c5e9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -116,24 +116,25 @@ void GLGizmoFlatten::on_render() glsafe(::glEnable(GL_BLEND)); if (selection.is_single_full_instance()) { - const Transform3d& m = selection.get_first_volume()->get_instance_transformation().get_matrix(); + const Transform3d& inst_matrix = selection.get_first_volume()->get_instance_transformation().get_matrix(); #if ENABLE_LEGACY_OPENGL_REMOVAL const Camera& camera = wxGetApp().plater()->get_camera(); - const Transform3d view_model_matrix = camera.get_view_matrix() * - Geometry::assemble_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * m; + const Transform3d model_matrix = Geometry::assemble_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * inst_matrix; + const Transform3d view_model_matrix = camera.get_view_matrix() * model_matrix; shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #else glsafe(::glPushMatrix()); glsafe(::glTranslatef(0.f, 0.f, selection.get_first_volume()->get_sla_shift_z())); - glsafe(::glMultMatrixd(m.data())); + glsafe(::glMultMatrixd(inst_matrix.data())); #endif // ENABLE_LEGACY_OPENGL_REMOVAL if (this->is_plane_update_necessary()) update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_RAYCAST_PICKING + m_planes_casters[i]->set_transform(model_matrix); m_planes[i].vbo.model.set_color(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR : DEFAULT_PLANE_COLOR); m_planes[i].vbo.model.render(); #else @@ -165,13 +166,15 @@ void GLGizmoFlatten::on_register_raycasters_for_picking() // the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account m_parent.set_raycaster_gizmos_on_top(true); + assert(m_planes_casters.empty()); + if (!m_planes.empty()) { const Selection& selection = m_parent.get_selection(); - const Transform3d matrix = Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * - selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); + const Transform3d matrix = Geometry::assemble_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * + selection.get_first_volume()->get_instance_transformation().get_matrix(); for (int i = 0; i < (int)m_planes.size(); ++i) { - m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_planes[i].vbo.mesh_raycaster, matrix); + m_planes_casters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_planes[i].vbo.mesh_raycaster, matrix)); } } } @@ -180,6 +183,7 @@ void GLGizmoFlatten::on_unregister_raycasters_for_picking() { m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo); m_parent.set_raycaster_gizmos_on_top(false); + m_planes_casters.clear(); } #else void GLGizmoFlatten::on_render_for_picking() @@ -238,7 +242,6 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { if (model_object != m_old_model_object) { m_planes.clear(); - m_planes_valid = false; #if ENABLE_RAYCAST_PICKING on_unregister_raycasters_for_picking(); #endif // ENABLE_RAYCAST_PICKING @@ -498,7 +501,6 @@ void GLGizmoFlatten::update_planes() #if ENABLE_RAYCAST_PICKING on_register_raycasters_for_picking(); #endif // ENABLE_RAYCAST_PICKING - m_planes_valid = true; } @@ -508,8 +510,8 @@ bool GLGizmoFlatten::is_plane_update_necessary() const if (m_state != On || ! mo || mo->instances.empty()) return false; - if (! m_planes_valid || mo != m_old_model_object - || mo->volumes.size() != m_volumes_matrices.size()) + if (m_planes.empty() || mo != m_old_model_object + || mo->volumes.size() != m_volumes_matrices.size()) return true; // We want to recalculate when the scale changes - some planes could (dis)appear. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp index 32d119fbc..0c2fb9c39 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -11,7 +11,6 @@ #include "slic3r/GUI/3DScene.hpp" #endif // ENABLE_LEGACY_OPENGL_REMOVAL - namespace Slic3r { enum class ModelVolumeType : int; @@ -51,8 +50,10 @@ private: Vec3d m_first_instance_mirror; std::vector m_planes; +#if ENABLE_RAYCAST_PICKING + std::vector> m_planes_casters; +#endif // ENABLE_RAYCAST_PICKING bool m_mouse_left_down = false; // for detection left_up of this gizmo - bool m_planes_valid = false; const ModelObject* m_old_model_object = nullptr; std::vector instances_matrices; diff --git a/src/slic3r/GUI/SceneRaycaster.cpp b/src/slic3r/GUI/SceneRaycaster.cpp index 4c6780fc5..49a59789e 100644 --- a/src/slic3r/GUI/SceneRaycaster.cpp +++ b/src/slic3r/GUI/SceneRaycaster.cpp @@ -33,13 +33,14 @@ SceneRaycaster::SceneRaycaster() { #endif // ENABLE_RAYCAST_PICKING_DEBUG } -std::shared_ptr SceneRaycaster::add_raycaster(EType type, int id, const MeshRaycaster& raycaster, const Transform3d& trafo) +std::shared_ptr SceneRaycaster::add_raycaster(EType type, int id, const MeshRaycaster& raycaster, + const Transform3d& trafo, bool use_back_faces) { switch (type) { - case EType::Bed: { return m_bed.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo)); } - case EType::Volume: { return m_volumes.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo)); } - case EType::Gizmo: { return m_gizmos.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo)); } - default: { assert(false); return nullptr; } + case EType::Bed: { return m_bed.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo, use_back_faces)); } + case EType::Volume: { return m_volumes.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo, use_back_faces)); } + case EType::Gizmo: { return m_gizmos.emplace_back(std::make_shared(encode_id(type, id), raycaster, trafo, use_back_faces)); } + default: { assert(false); return nullptr; } }; } @@ -107,6 +108,7 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came auto test_raycasters = [this, is_closest, clipping_plane](EType type, const Vec2d& mouse_pos, const Camera& camera, HitResult& ret) { const ClippingPlane* clip_plane = (clipping_plane != nullptr && type == EType::Volume) ? clipping_plane : nullptr; std::vector>* raycasters = get_raycasters(type); + const Vec3f camera_forward = camera.get_dir_forward().cast(); HitResult current_hit = { type }; for (std::shared_ptr item : *raycasters) { if (!item->is_active()) @@ -116,10 +118,11 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came const Transform3d& trafo = item->get_transform(); if (item->get_raycaster()->closest_hit(mouse_pos, trafo, camera, current_hit.position, current_hit.normal, clip_plane)) { current_hit.position = (trafo * current_hit.position.cast()).cast(); - if (is_closest(camera, current_hit.position)) { - const Matrix3d normal_matrix = (Matrix3d)trafo.matrix().block(0, 0, 3, 3).inverse().transpose(); - current_hit.normal = (normal_matrix * current_hit.normal.cast()).normalized().cast(); - ret = current_hit; + current_hit.normal = (trafo.matrix().block(0, 0, 3, 3).inverse().transpose() * current_hit.normal.cast()).normalized().cast(); + if (item->use_back_faces() || current_hit.normal.dot(camera_forward) < 0.0f){ + if (is_closest(camera, current_hit.position)) { + ret = current_hit; + } } } } diff --git a/src/slic3r/GUI/SceneRaycaster.hpp b/src/slic3r/GUI/SceneRaycaster.hpp index c5c52c4b7..8993c51a9 100644 --- a/src/slic3r/GUI/SceneRaycaster.hpp +++ b/src/slic3r/GUI/SceneRaycaster.hpp @@ -18,17 +18,19 @@ class SceneRaycasterItem { int m_id{ -1 }; bool m_active{ true }; + bool m_use_back_faces{ false }; const MeshRaycaster* m_raycaster; Transform3d m_trafo; public: - SceneRaycasterItem(int id, const MeshRaycaster& raycaster, const Transform3d& trafo) - : m_id(id), m_raycaster(&raycaster), m_trafo(trafo) + SceneRaycasterItem(int id, const MeshRaycaster& raycaster, const Transform3d& trafo, bool use_back_faces = false) + : m_id(id), m_raycaster(&raycaster), m_trafo(trafo), m_use_back_faces(use_back_faces) {} int get_id() const { return m_id; } bool is_active() const { return m_active; } void set_active(bool active) { m_active = active; } + bool use_back_faces() const { return m_use_back_faces; } const MeshRaycaster* get_raycaster() const { return m_raycaster; } const Transform3d& get_transform() const { return m_trafo; } void set_transform(const Transform3d& trafo) { m_trafo = trafo; } @@ -80,7 +82,8 @@ private: public: SceneRaycaster(); - std::shared_ptr add_raycaster(EType type, int picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo); + std::shared_ptr 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 item);