From 3c0e33136358c6f32ecf507c09021a7d72014dee Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 15 Nov 2022 12:17:18 +0100 Subject: [PATCH] Gizmo measure modified to accept single full instance selection, to combine the volumes meshes into a single mesh and pass it to the back end after transform it in world coordinates Changes embedded into tech ENABLE_GIZMO_MEASURE_WORLD_COORDINATES --- src/libslic3r/Measure.cpp | 37 ++++ src/libslic3r/Measure.hpp | 19 +- src/libslic3r/Technologies.hpp | 2 + src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 215 ++++++++++++++++++++++- src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp | 35 ++++ src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 13 ++ src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp | 7 + src/slic3r/GUI/Selection.cpp | 13 ++ src/slic3r/GUI/Selection.hpp | 4 + 9 files changed, 338 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index 43b9782a8..1ffd72c14 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -45,6 +45,9 @@ public: std::optional get_feature(size_t face_idx, const Vec3d& point) const; std::vector> get_planes_triangle_indices() const; const std::vector& get_plane_features(unsigned int plane_id) const; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const TriangleMesh& get_mesh() const; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES private: void update_planes(); @@ -52,7 +55,11 @@ private: std::vector m_planes; std::vector m_face_to_plane; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + TriangleMesh m_mesh; +#else const indexed_triangle_set& m_its; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES }; @@ -61,7 +68,11 @@ private: MeasuringImpl::MeasuringImpl(const indexed_triangle_set& its) +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +: m_mesh(its) +#else : m_its{its} +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES { update_planes(); extract_features(); @@ -74,10 +85,17 @@ void MeasuringImpl::update_planes() // Now we'll go through all the facets and append Points of facets sharing the same normal. // This part is still performed in mesh coordinate system. +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const size_t num_of_facets = m_mesh.its.indices.size(); + m_face_to_plane.resize(num_of_facets, size_t(-1)); + const std::vector face_normals = its_face_normals(m_mesh.its); + const std::vector face_neighbors = its_face_neighbors(m_mesh.its); +#else const size_t num_of_facets = m_its.indices.size(); m_face_to_plane.resize(num_of_facets, size_t(-1)); const std::vector face_normals = its_face_normals(m_its); const std::vector face_neighbors = its_face_neighbors(m_its); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES std::vector facet_queue(num_of_facets, 0); int facet_queue_cnt = 0; const stl_normal* normal_ptr = nullptr; @@ -126,7 +144,11 @@ void MeasuringImpl::update_planes() assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); })); // Now we will walk around each of the planes and save vertices which form the border. +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + SurfaceMesh sm(m_mesh.its); +#else SurfaceMesh sm(m_its); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) { const auto& facets = m_planes[plane_id].facets; m_planes[plane_id].borders.clear(); @@ -508,6 +530,12 @@ const std::vector& MeasuringImpl::get_plane_features(unsigned in return m_planes[plane_id].surface_features; } +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +const TriangleMesh& MeasuringImpl::get_mesh() const +{ + return this->m_mesh; +} +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES @@ -549,6 +577,13 @@ const std::vector& Measuring::get_plane_features(unsigned int pl return priv->get_plane_features(plane_id); } +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +const TriangleMesh& Measuring::get_mesh() const +{ + return priv->get_mesh(); +} +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const AngleAndEdges AngleAndEdges::Dummy = { 0.0, Vec3d::Zero(), { Vec3d::Zero(), Vec3d::Zero() }, { Vec3d::Zero(), Vec3d::Zero() }, 0.0, true }; static AngleAndEdges angle_edge_edge(const std::pair& e1, const std::pair& e2) @@ -1147,6 +1182,7 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& return result; } +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES void DistAndPoints::transform(const Transform3d& trafo) { from = trafo * from; to = trafo * to; @@ -1167,6 +1203,7 @@ void AngleAndEdges::transform(const Transform3d& trafo) { const double average_scale = 0.5 * (new_e1.norm() / old_e1.norm() + new_e2.norm() / old_e2.norm()); radius = average_scale * radius; } +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES diff --git a/src/libslic3r/Measure.hpp b/src/libslic3r/Measure.hpp index ede8c634e..b2e2008d1 100644 --- a/src/libslic3r/Measure.hpp +++ b/src/libslic3r/Measure.hpp @@ -87,9 +87,11 @@ class MeasuringImpl; class Measuring { public: - // Construct the measurement object on a given its. The its must remain - // valid and unchanged during the whole lifetime of the object. - explicit Measuring(const indexed_triangle_set& its); + // Construct the measurement object on a given its. +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + // The its must remain valid and unchanged during the whole lifetime of the object. +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + explicit Measuring(const indexed_triangle_set& its); ~Measuring(); // Return a reference to a list of all features identified on the its. @@ -108,6 +110,11 @@ public: // Returns the surface features of the plane with the given index const std::vector& get_plane_features(unsigned int plane_id) const; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + // Returns the mesh used for measuring + const TriangleMesh& get_mesh() const; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + private: std::unique_ptr priv; }; @@ -119,7 +126,9 @@ struct DistAndPoints { Vec3d from; Vec3d to; +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES void transform(const Transform3d& trafo); +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES }; struct AngleAndEdges { @@ -132,7 +141,9 @@ struct AngleAndEdges { double radius; bool coplanar; +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES void transform(const Transform3d& trafo); +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES static const AngleAndEdges Dummy; }; @@ -151,6 +162,7 @@ struct MeasurementResult { return angle.has_value() || distance_infinite.has_value() || distance_strict.has_value() || distance_xyz.has_value(); } +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES void transform(const Transform3d& trafo) { if (angle.has_value()) angle->transform(trafo); @@ -161,6 +173,7 @@ struct MeasurementResult { distance_xyz = (distance_strict->to - distance_strict->from).cwiseAbs(); } } +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES }; // Returns distance/angle between two SurfaceFeatures. diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index a3e72cf0c..9e7c660ae 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -64,6 +64,8 @@ // Enable picking using raytracing #define ENABLE_RAYCAST_PICKING (1 && ENABLE_LEGACY_OPENGL_REMOVAL) #define ENABLE_RAYCAST_PICKING_DEBUG (0 && ENABLE_RAYCAST_PICKING) +// Enable gizmo measure combining volumes meshes and passing them to the backend in world coordinates +#define ENABLE_GIZMO_MEASURE_WORLD_COORDINATES (1 && ENABLE_2_5_0_ALPHA1) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 8b26422c8..5ae906eac 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -5,9 +5,11 @@ #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp" -#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" #include "libslic3r/Model.hpp" +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES #include "libslic3r/PresetBundle.hpp" #include "libslic3r/MeasureUtils.hpp" @@ -242,7 +244,10 @@ private: TransformHelper::Cache TransformHelper::s_cache = { { 0, 0, 0, 0 }, Matrix4d::Identity(), Transform3d::Identity() }; GLGizmoMeasure::GLGizmoMeasure(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +: GLGizmoBase(parent, icon_filename, sprite_id) +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +, m_raycaster(nullptr) +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES { GLModel::Geometry sphere_geometry = smooth_sphere(16, 7.5f); m_sphere.mesh_raycaster = std::make_unique(std::make_shared(sphere_geometry.get_as_indexed_triangle_set())); @@ -370,8 +375,10 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) if (m_selected_features != selected_features_old && m_selected_features.second.feature.has_value()) { m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES // transform to world coordinates m_measurement_result.transform(m_volume_matrix); +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES } m_imgui->set_requires_extra_frame(); @@ -419,6 +426,9 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) void GLGizmoMeasure::data_changed() { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + update_if_needed(); +#else const Selection& selection = m_parent.get_selection(); const ModelObject* model_object = nullptr; const ModelVolume* model_volume = nullptr; @@ -429,13 +439,16 @@ void GLGizmoMeasure::data_changed() } if (model_object != m_old_model_object || model_volume != m_old_model_volume) update_if_needed(); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES m_last_inv_zoom = 0.0f; m_last_plane_idx = -1; if (m_pending_scale) { m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES // transform to world coordinates m_measurement_result.transform(m_volume_matrix); +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES m_pending_scale = false; } else @@ -512,6 +525,9 @@ void GLGizmoMeasure::on_set_state() m_editing_distance = false; m_is_editing_distance_first_frame = true; m_measuring.reset(); +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + m_raycaster.release(); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES } else { m_mode = EMode::FeatureSelection; @@ -528,10 +544,12 @@ void GLGizmoMeasure::on_set_state() } } +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES CommonGizmosDataID GLGizmoMeasure::on_get_requirements() const { return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::Raycaster)); } +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES std::string GLGizmoMeasure::on_get_name() const { @@ -543,9 +561,15 @@ bool GLGizmoMeasure::on_is_activable() const const Selection& selection = m_parent.get_selection(); bool res = (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) ? selection.is_single_full_instance() : +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier(); + if (res) + res &= !selection.contains_sinking_volumes(); +#else selection.is_single_volume() || selection.is_single_volume_instance(); if (res) res &= !selection.get_first_volume()->is_sinking(); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES return res; } @@ -562,8 +586,10 @@ void GLGizmoMeasure::on_render() const Selection& selection = m_parent.get_selection(); +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES if ((wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA && selection.is_single_full_instance()) || (selection.is_single_volume() || selection.is_single_volume_instance())) { +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES update_if_needed(); const Camera& camera = wxGetApp().plater()->get_camera(); @@ -572,7 +598,11 @@ void GLGizmoMeasure::on_render() Vec3f position_on_model; Vec3f normal_on_model; size_t model_facet_idx; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const bool mouse_on_object = m_raycaster.raycaster()->unproject_on_mesh(m_mouse_pos, Transform3d::Identity(), camera, position_on_model, normal_on_model, nullptr, &model_facet_idx); +#else const bool mouse_on_object = m_c->raycaster()->raycasters().front()->unproject_on_mesh(m_mouse_pos, m_volume_matrix, camera, position_on_model, normal_on_model, nullptr, &model_facet_idx); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES const bool is_hovering_on_feature = (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection) && m_hover_id != -1; auto update_circle = [this, inv_zoom]() { @@ -581,7 +611,11 @@ void GLGizmoMeasure::on_render() m_last_circle = m_curr_feature; m_circle.reset(); const auto [center, radius, normal] = m_curr_feature->get_circle(); +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), Transform3f::Identity()); +#else GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), m_volume_matrix.cast()); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES m_circle.mesh_raycaster = std::make_unique(std::make_shared(circle_geometry.get_as_indexed_triangle_set())); m_circle.model.init_from(std::move(circle_geometry)); return true; @@ -639,7 +673,11 @@ void GLGizmoMeasure::on_render() const auto [idx, normal, point] = m_curr_feature->get_plane(); if (m_last_plane_idx != idx) { m_last_plane_idx = idx; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const indexed_triangle_set& its = m_measuring->get_mesh().its; +#else const indexed_triangle_set its = (m_old_model_volume != nullptr) ? m_old_model_volume->mesh().its : m_old_model_object->volumes.front()->mesh().its; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES const std::vector> planes_triangles = m_measuring->get_planes_triangle_indices(); GLModel::Geometry init_data = init_plane_data(its, planes_triangles, idx); m_plane.reset(); @@ -689,12 +727,20 @@ void GLGizmoMeasure::on_render() if (extra.has_value() && m_hover_id == POINT_ID) m_curr_point_on_feature_position = *extra; else +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + m_curr_point_on_feature_position = position_on_feature(EDGE_ID, camera, [](const Vec3f& v) { return Vec3f(0.0f, 0.0f, v.z()); }); +#else m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(EDGE_ID, camera, [](const Vec3f& v) { return Vec3f(0.0f, 0.0f, v.z()); }); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES break; } case Measure::SurfaceFeatureType::Plane: { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + m_curr_point_on_feature_position = position_on_feature(PLANE_ID, camera); +#else m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(PLANE_ID, camera); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES break; } case Measure::SurfaceFeatureType::Circle: @@ -704,9 +750,17 @@ void GLGizmoMeasure::on_render() m_curr_point_on_feature_position = center; else { const Vec3d world_pof = position_on_feature(CIRCLE_ID, camera, [](const Vec3f& v) { return v; }); +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Eigen::Hyperplane plane(normal, center); +#else const Eigen::Hyperplane plane(m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal, m_volume_matrix * center); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES const Transform3d local_to_model_matrix = Geometry::translation_transform(center) * Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), normal); +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Vec3d local_proj = local_to_model_matrix.inverse() * plane.projection(world_pof); +#else const Vec3d local_proj = local_to_model_matrix.inverse() * m_volume_matrix.inverse() * plane.projection(world_pof); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES double angle = std::atan2(local_proj.y(), local_proj.x()); if (angle < 0.0) angle += 2.0 * double(M_PI); @@ -767,8 +821,12 @@ void GLGizmoMeasure::on_render() default: { assert(false); break; } case Measure::SurfaceFeatureType::Point: { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Transform3d feature_matrix = Geometry::translation_transform(feature.get_point()) * Geometry::scale_transform(inv_zoom); +#else const Vec3d position = TransformHelper::model_to_world(feature.get_point(), m_volume_matrix); const Transform3d feature_matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES set_matrix_uniforms(feature_matrix); set_emission_uniform(colors.front(), hover); m_sphere.model.set_color(colors.front()); @@ -785,8 +843,12 @@ void GLGizmoMeasure::on_render() const auto& [center, radius, normal] = feature.get_circle(); // render center if (update_raycasters_transform) { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Transform3d center_matrix = Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom); +#else const Vec3d center_world = TransformHelper::model_to_world(center, m_volume_matrix); const Transform3d center_matrix = Geometry::translation_transform(center_world) * Geometry::scale_transform(inv_zoom); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES set_matrix_uniforms(center_matrix); set_emission_uniform(colors.front(), hover); m_sphere.model.set_color(colors.front()); @@ -809,7 +871,11 @@ void GLGizmoMeasure::on_render() } else { GLModel circle; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), Transform3f::Identity()); +#else GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), m_volume_matrix.cast()); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES circle.init_from(std::move(circle_geometry)); set_emission_uniform(colors.back(), hover); circle.set_color(colors.back()); @@ -825,8 +891,12 @@ void GLGizmoMeasure::on_render() if (update_raycasters_transform) { const std::optional extra = feature.get_extra_point(); if (extra.has_value()) { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Transform3d point_matrix = Geometry::translation_transform(*extra) * Geometry::scale_transform(inv_zoom); +#else const Vec3d extra_world = TransformHelper::model_to_world(*extra, m_volume_matrix); const Transform3d point_matrix = Geometry::translation_transform(extra_world) * Geometry::scale_transform(inv_zoom); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES set_matrix_uniforms(point_matrix); set_emission_uniform(colors.front(), hover); m_sphere.model.set_color(colors.front()); @@ -838,11 +908,17 @@ void GLGizmoMeasure::on_render() } // render edge if (m_mode != EMode::CenterSelection) { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Transform3d edge_matrix = Geometry::translation_transform(from) * + Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), to - from) * + Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to - from).norm() }); +#else const Vec3d from_world = TransformHelper::model_to_world(from, m_volume_matrix); const Vec3d to_world = TransformHelper::model_to_world(to, m_volume_matrix); const Transform3d edge_matrix = Geometry::translation_transform(from_world) * Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), to_world - from_world) * Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to_world - from_world).norm() }); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES set_matrix_uniforms(edge_matrix); set_emission_uniform(colors.back(), hover); m_cylinder.model.set_color(colors.back()); @@ -861,7 +937,11 @@ void GLGizmoMeasure::on_render() if (colors.front() != m_parent.get_selection().get_first_volume()->render_color) { const auto& [idx, normal, pt] = feature.get_plane(); assert(idx < m_plane_models_cache.size()); +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + set_matrix_uniforms(Transform3d::Identity()); +#else set_matrix_uniforms(m_volume_matrix); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES set_emission_uniform(colors.front(), hover); m_plane_models_cache[idx].set_color(colors.front()); m_plane_models_cache[idx].render(); @@ -869,7 +949,11 @@ void GLGizmoMeasure::on_render() if (update_raycasters_transform) { auto it = m_raycasters.find(PLANE_ID); if (it != m_raycasters.end() && it->second != nullptr) +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + it->second->set_transform(Transform3d::Identity()); +#else it->second->set_transform(m_volume_matrix); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES } break; } @@ -924,7 +1008,11 @@ void GLGizmoMeasure::on_render() auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(), [](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_1_ID; }); if (it != m_selection_raycasters.end()) +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + (*it)->set_transform(Geometry::translation_transform(m_selected_features.first.feature->get_point()) * Geometry::scale_transform(inv_zoom)); +#else (*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.first.feature->get_point()) * Geometry::scale_transform(inv_zoom)); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES } } if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) { @@ -934,14 +1022,22 @@ void GLGizmoMeasure::on_render() auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(), [](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_2_ID; }); if (it != m_selection_raycasters.end()) +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + (*it)->set_transform(Geometry::translation_transform(m_selected_features.second.feature->get_point()) * Geometry::scale_transform(inv_zoom)); +#else (*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.second.feature->get_point()) * Geometry::scale_transform(inv_zoom)); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES } } if (is_hovering_on_feature && m_curr_point_on_feature_position.has_value()) { if (m_hover_id != POINT_ID) { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Transform3d matrix = Geometry::translation_transform(*m_curr_point_on_feature_position) * Geometry::scale_transform(inv_zoom); +#else const Vec3d position = TransformHelper::model_to_world(*m_curr_point_on_feature_position, m_volume_matrix); const Transform3d matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES set_matrix_uniforms(matrix); const ColorRGBA color = hover_selection_color(); set_emission_uniform(color, true); @@ -954,7 +1050,9 @@ void GLGizmoMeasure::on_render() if (old_cullface) glsafe(::glEnable(GL_CULL_FACE)); +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES } +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES render_dimensioning(); } @@ -971,6 +1069,24 @@ void GLGizmoMeasure::update_if_needed() } }; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + auto do_update = [this, update_plane_models_cache](const std::vector& volumes_cache, const Selection& selection) { + TriangleMesh composite_mesh; + for (const auto& vol : volumes_cache) { +// if (selection.is_single_full_instance() && vol.volume->is_modifier()) +// continue; + + TriangleMesh volume_mesh = vol.volume->mesh(); + volume_mesh.transform(vol.instance->get_transformation().get_matrix() * vol.volume->get_transformation().get_matrix()); + composite_mesh.merge(volume_mesh); + } + + m_measuring.reset(new Measure::Measuring(composite_mesh.its)); + update_plane_models_cache(m_measuring->get_mesh().its); + m_raycaster.update_from(m_measuring->get_mesh()); + m_volumes_cache = volumes_cache; + }; +#else auto do_update = [this, update_plane_models_cache](const ModelObject* object, const ModelVolume* volume) { const indexed_triangle_set& its = (volume != nullptr) ? volume->mesh().its : object->volumes.front()->mesh().its; m_measuring.reset(new Measure::Measuring(its)); @@ -980,24 +1096,44 @@ void GLGizmoMeasure::update_if_needed() // Let's save what we calculated it from: m_volumes_matrices.clear(); m_volumes_types.clear(); - m_first_instance_scale = Vec3d::Ones(); + m_first_instance_scale = Vec3d::Ones(); m_first_instance_mirror = Vec3d::Ones(); if (object != nullptr) { for (const ModelVolume* vol : object->volumes) { m_volumes_matrices.push_back(vol->get_matrix()); m_volumes_types.push_back(vol->type()); } - m_first_instance_scale = object->instances.front()->get_scaling_factor(); + m_first_instance_scale = object->instances.front()->get_scaling_factor(); m_first_instance_mirror = object->instances.front()->get_mirror(); } m_old_model_object = object; m_old_model_volume = volume; }; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES const Selection& selection = m_parent.get_selection(); if (selection.is_empty()) return; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Selection::IndicesList& idxs = selection.get_volume_idxs(); + std::vector volumes_cache; + volumes_cache.reserve(idxs.size()); + for (unsigned int idx : idxs) { + const GLVolume* v = selection.get_volume(idx); + const ModelObject* obj = selection.get_model()->objects[v->object_idx()]; + const ModelInstance* inst = obj->instances[v->instance_idx()]; + const ModelVolume* vol = obj->volumes[v->volume_idx()]; + const VolumeCacheItem item = { obj, inst, vol, inst->get_matrix() * vol->get_matrix() }; + volumes_cache.emplace_back(item); + } + + if (m_state != On || volumes_cache.empty()) + return; + + if (m_measuring == nullptr || m_volumes_cache != volumes_cache) + do_update(volumes_cache, selection); +#else m_volume_matrix = selection.get_first_volume()->world_matrix(); const ModelObject* mo = m_c->selection_info()->model_object(); @@ -1026,6 +1162,7 @@ void GLGizmoMeasure::update_if_needed() break; } } +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES } void GLGizmoMeasure::disable_scene_raycasters() @@ -1145,6 +1282,62 @@ void GLGizmoMeasure::render_dimensioning() const double ratio = new_value / old_value; wxGetApp().plater()->take_snapshot(_L("Scale")); +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + struct TrafoData + { + double ratio; + Vec3d old_pivot; + Vec3d new_pivot; + Transform3d scale_matrix; + + TrafoData(double ratio, const Vec3d& pivot) { + this->ratio = ratio; + this->scale_matrix = Geometry::scale_transform(ratio); + this->old_pivot = pivot; + this->new_pivot = { pivot.x(), pivot.y(), (this->scale_matrix * pivot).z() }; + } + + Vec3d transform(const Vec3d& point) const { + return this->scale_matrix * (point - this->old_pivot) + this->new_pivot; + } + }; + + auto scale_feature = [this](Measure::SurfaceFeature& feature, const TrafoData& trafo_data) { + switch (feature.get_type()) + { + case Measure::SurfaceFeatureType::Point: + { + feature = Measure::SurfaceFeature(trafo_data.transform(feature.get_point())); + break; + } + case Measure::SurfaceFeatureType::Edge: + { + const auto [from, to] = feature.get_edge(); + const std::optional extra = feature.get_extra_point(); + const std::optional new_extra = extra.has_value() ? trafo_data.transform(*extra) : extra; + feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Edge, trafo_data.transform(from), trafo_data.transform(to), new_extra); + break; + } + case Measure::SurfaceFeatureType::Circle: + { + const auto [center, radius, normal] = feature.get_circle(); + feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Circle, trafo_data.transform(center), normal, std::nullopt, trafo_data.ratio * radius); + break; + } + case Measure::SurfaceFeatureType::Plane: + { + const auto [idx, normal, origin] = feature.get_plane(); + feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Plane, normal, trafo_data.transform(origin), std::nullopt, idx); + break; + } + } + }; + + const TrafoData trafo_data(ratio, m_parent.get_selection().get_bounding_box().center()); + scale_feature(*m_selected_features.first.feature, trafo_data); + scale_feature(*m_selected_features.second.feature, trafo_data); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + TransformationType type; type.set_world(); type.set_relative(); @@ -1203,8 +1396,10 @@ void GLGizmoMeasure::render_dimensioning() assert(f1.get_type() == Measure::SurfaceFeatureType::Point && f2.get_type() == Measure::SurfaceFeatureType::Edge); std::pair e = f2.get_edge(); // Transform to world coordinates +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES e.first = TransformHelper::model_to_world(e.first, m_volume_matrix); e.second = TransformHelper::model_to_world(e.second, m_volume_matrix); +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES const Vec3d v_proj = m_measurement_result.distance_infinite->to; @@ -1485,15 +1680,21 @@ void GLGizmoMeasure::render_debug_dialog() { case Measure::SurfaceFeatureType::Point: { +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(item.feature->get_point()), ImGui::GetStyleColorVec4(ImGuiCol_Text)); +#else const Vec3d position = m_volume_matrix * item.feature->get_point(); add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text)); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES break; } case Measure::SurfaceFeatureType::Edge: { auto [from, to] = item.feature->get_edge(); +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES from = m_volume_matrix * from; to = m_volume_matrix * to; +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text)); break; @@ -1501,8 +1702,10 @@ void GLGizmoMeasure::render_debug_dialog() case Measure::SurfaceFeatureType::Plane: { auto [idx, normal, origin] = item.feature->get_plane(); +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES origin = m_volume_matrix * origin; normal = m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal; +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(idx), ImGui::GetStyleColorVec4(ImGuiCol_Text)); @@ -1511,9 +1714,13 @@ void GLGizmoMeasure::render_debug_dialog() case Measure::SurfaceFeatureType::Circle: { auto [center, radius, normal] = item.feature->get_circle(); +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + const Vec3d on_circle = center + radius * Measure::get_orthogonal(normal, true); +#else const Vec3d on_circle = m_volume_matrix * (center + radius * Measure::get_orthogonal(normal, true)); center = m_volume_matrix * center; normal = (m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal).normalized(); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES radius = (on_circle - center).norm(); add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp index 7bfc2e8c9..606012f7c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp @@ -5,10 +5,16 @@ #include "slic3r/GUI/GLModel.hpp" #include "slic3r/GUI/GUI_Utils.hpp" #include "libslic3r/Measure.hpp" +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" +#include "libslic3r/Model.hpp" +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES namespace Slic3r { +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES class ModelVolume; +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES enum class ModelVolumeType : int; @@ -68,6 +74,23 @@ class GLGizmoMeasure : public GLGizmoBase } }; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + struct VolumeCacheItem + { + const ModelObject* object{ nullptr }; + const ModelInstance* instance{ nullptr }; + const ModelVolume* volume{ nullptr }; + Transform3d world_trafo; + + bool operator == (const VolumeCacheItem& other) const { + return this->object == other.object && this->instance == other.instance && this->volume == other.volume && + this->world_trafo.isApprox(other.world_trafo); + } + }; + + std::vector m_volumes_cache; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + EMode m_mode{ EMode::FeatureSelection }; Measure::MeasurementResult m_measurement_result; @@ -85,7 +108,13 @@ class GLGizmoMeasure : public GLGizmoBase }; Dimensioning m_dimensioning; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + // Uses a standalone raycaster and not the shared one because of the + // difference in how the mesh is updated + CommonGizmosDataObjects::Raycaster m_raycaster; +#else Transform3d m_volume_matrix{ Transform3d::Identity() }; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES std::vector m_plane_models_cache; std::map> m_raycasters; std::vector> m_selection_raycasters; @@ -100,17 +129,21 @@ class GLGizmoMeasure : public GLGizmoBase std::vector m_scene_raycasters; // These hold information to decide whether recalculation is necessary: +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES std::vector m_volumes_matrices; std::vector m_volumes_types; Vec3d m_first_instance_scale{ Vec3d::Ones() }; Vec3d m_first_instance_mirror{ Vec3d::Ones() }; +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES float m_last_inv_zoom{ 0.0f }; std::optional m_last_circle; int m_last_plane_idx{ -1 }; bool m_mouse_left_down{ false }; // for detection left_up of this gizmo +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES const ModelObject* m_old_model_object{ nullptr }; const ModelVolume* m_old_model_volume{ nullptr }; +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES Vec2d m_mouse_pos{ Vec2d::Zero() }; @@ -153,7 +186,9 @@ protected: bool on_is_activable() const override; void on_render() override; void on_set_state() override; +#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES CommonGizmosDataID on_get_requirements() const override; +#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES virtual void on_render_input_window(float x, float y, float bottom_limit) override; virtual void on_register_raycasters_for_picking() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 394e879b7..dca64a526 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -327,6 +327,19 @@ const TriangleMesh* HollowedMesh::get_hollowed_interior() const } +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +void Raycaster::update_from(const TriangleMesh& mesh) +{ + std::vector meshes = { &mesh }; + if (meshes != m_old_meshes) { + wxBusyCursor wait; + m_raycasters.clear(); + m_raycasters.emplace_back(new MeshRaycaster(std::make_shared(mesh))); + m_old_meshes = meshes; + } + validate(); +} +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES void Raycaster::on_update() diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp index 42faa25f8..b02e3a920 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp @@ -137,6 +137,9 @@ protected: virtual void on_update() = 0; CommonGizmosDataPool* get_pool() const { return m_common; } +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + void validate() { m_is_valid = true; } +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES private: bool m_is_valid = false; @@ -242,6 +245,10 @@ public: const MeshRaycaster* raycaster() const { assert(m_raycasters.size() == 1); return m_raycasters.front().get(); } std::vector raycasters() const; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + void update_from(const TriangleMesh& mesh); +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + protected: void on_update() override; void on_release() override; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 9a4169b31..2e50fc37c 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -602,6 +602,19 @@ bool Selection::contains_any_volume(const std::vector& volume_idxs return false; } +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES +bool Selection::contains_sinking_volumes(bool ignore_modifiers) const +{ + for (const GLVolume* v : *m_volumes) { + if (!ignore_modifiers || !v->is_modifier) { + if (v->is_sinking()) + return true; + } + } + return false; +} +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + bool Selection::matches(const std::vector& volume_idxs) const { unsigned int count = 0; diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index c4720a308..0064f2799 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -337,6 +337,10 @@ public: bool contains_all_volumes(const std::vector& volume_idxs) const; // returns true if the selection contains at least one of the given indices bool contains_any_volume(const std::vector& volume_idxs) const; +#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES + // returns true if the selection contains any sinking volume + bool contains_sinking_volumes(bool ignore_modifiers = true) const; +#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES // returns true if the selection contains all and only the given indices bool matches(const std::vector& volume_idxs) const;