From c12eeee12f9e2c91a9dfe7905f1370143805f038 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 2 Oct 2023 14:26:36 +0200 Subject: [PATCH] SPE-1926: Tech ENABLE_CGAL_BOUNDING_SPHERE - Use selection's bounding sphere center as pivot for rotations --- src/libslic3r/Technologies.hpp | 3 ++ src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 10 ++++ src/slic3r/GUI/Selection.cpp | 61 +++++++++++++++++++++++++ src/slic3r/GUI/Selection.hpp | 15 ++++++ 4 files changed, 89 insertions(+) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 6c295279ad..c46570c839 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -61,4 +61,7 @@ // Enable imgui dialog which allows to set the parameters used to export binarized gcode #define ENABLE_BINARIZED_GCODE_DEBUG_WINDOW 0 +// Enable use selection's bounding sphere center as pivot for rotations +#define ENABLE_CGAL_BOUNDING_SPHERE 1 + #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 053f24418c..686f1f0c1e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -204,10 +204,20 @@ void GLGizmoRotate::init_data_from_selection(const Selection& selection) const auto [box, box_trafo] = m_force_local_coordinate ? selection.get_bounding_box_in_reference_system(ECoordinatesType::Local) : selection.get_bounding_box_in_current_reference_system(); m_bounding_box = box; +#if ENABLE_CGAL_BOUNDING_SPHERE + const std::pair sphere = selection.get_bounding_sphere(); + m_center = sphere.first; + m_radius = Offset + sphere.second; +#else m_center = box_trafo.translation(); +#endif // ENABLE_CGAL_BOUNDING_SPHERE m_orient_matrix = box_trafo; +#if ENABLE_CGAL_BOUNDING_SPHERE + m_orient_matrix.translation() = m_center; +#else m_radius = Offset + m_bounding_box.radius(); +#endif // ENABLE_CGAL_BOUNDING_SPHERE m_snap_coarse_in_radius = m_radius / 3.0f; m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; m_snap_fine_in_radius = m_radius; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index b6847859eb..d659f5cd29 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -29,6 +29,12 @@ #include #include +#if ENABLE_CGAL_BOUNDING_SPHERE +#include +#include +#include +#endif // ENABLE_CGAL_BOUNDING_SPHERE + static const Slic3r::ColorRGBA UNIFORM_SCALE_COLOR = Slic3r::ColorRGBA::ORANGE(); static const Slic3r::ColorRGBA SOLID_PLANE_COLOR = Slic3r::ColorRGBA::ORANGE(); static const Slic3r::ColorRGBA TRANSPARENT_PLANE_COLOR = { 0.8f, 0.8f, 0.8f, 0.5f }; @@ -906,6 +912,41 @@ BoundingBoxf Selection::get_screen_space_bounding_box() return ss_box; } +#if ENABLE_CGAL_BOUNDING_SPHERE +const std::pair Selection::get_bounding_sphere() const +{ + if (!m_bounding_sphere.has_value()) { + std::optional>* sphere = const_cast>*>(&m_bounding_sphere); + *sphere = { Vec3d::Zero(), 0.0 }; + + using K = CGAL::Simple_cartesian; + using Traits = CGAL::Min_sphere_of_points_d_traits_3; + using Min_sphere = CGAL::Min_sphere_of_spheres_d; + using Point = K::Point_3; + using Sphere = Traits::Sphere; + + std::vector points; + if (m_valid) { + for (unsigned int i : m_list) { + const TriangleMesh* hull = (*m_volumes)[i]->convex_hull(); + const Transform3d& matrix = (*m_volumes)[i]->world_matrix(); + for (const Vec3f& v : hull->its.vertices) { + const Vec3d vv = matrix * v.cast(); + points.push_back(Point(vv.x(), vv.y(), vv.z())); + } + } + + Min_sphere ms(points.begin(), points.end()); + const float* center_x = ms.center_cartesian_begin(); + (*sphere)->first = { *center_x, *(center_x + 1), *(center_x + 2) }; + (*sphere)->second = ms.radius(); + } + } + + return *m_bounding_sphere; +} +#endif // ENABLE_CGAL_BOUNDING_SPHERE + void Selection::setup_cache() { if (!m_valid) @@ -993,15 +1034,27 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ rotation_matrix = inst_matrix_no_offset.inverse() * inst_rotation_matrix * rotation_matrix * inst_rotation_matrix.inverse() * inst_matrix_no_offset; // rotate around selection center +#if ENABLE_CGAL_BOUNDING_SPHERE + const Vec3d inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * (m_cache.rotation_pivot - inst_trafo.get_offset()); +#else const Vec3d inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * (m_cache.dragging_center - inst_trafo.get_offset()); +#endif // ENABLE_CGAL_BOUNDING_SPHERE rotation_matrix = Geometry::translation_transform(inst_pivot) * rotation_matrix * Geometry::translation_transform(-inst_pivot); } +#if ENABLE_CGAL_BOUNDING_SPHERE + transform_instance_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot); +#else transform_instance_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); +#endif // ENABLE_CGAL_BOUNDING_SPHERE } else { if (!is_single_volume_or_modifier()) { assert(transformation_type.world()); +#if ENABLE_CGAL_BOUNDING_SPHERE + transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot); +#else transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); +#endif // ENABLE_CGAL_BOUNDING_SPHERE } else { if (transformation_type.instance()) { @@ -1027,7 +1080,11 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ vol_rotation_matrix.inverse() * inst_scale_matrix * vol_matrix_no_offset; } } +#if ENABLE_CGAL_BOUNDING_SPHERE + transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot); +#else transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); +#endif // ENABLE_CGAL_BOUNDING_SPHERE } } } @@ -2036,6 +2093,10 @@ void Selection::set_caches() m_cache.sinking_volumes.push_back(i); } m_cache.dragging_center = get_bounding_box().center(); +#if ENABLE_CGAL_BOUNDING_SPHERE + m_cache.rotation_pivot = get_bounding_sphere().first; +// m_cache.dragging_center = m_cache.rotation_pivot; +#endif // ENABLE_CGAL_BOUNDING_SPHERE } void Selection::do_add_volume(unsigned int volume_idx) diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index d4b7326afd..1a2c67ecf6 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -114,6 +114,9 @@ private: ObjectIdxsToInstanceIdxsMap content; // List of ids of the volumes which are sinking when starting dragging std::vector sinking_volumes; +#if ENABLE_CGAL_BOUNDING_SPHERE + Vec3d rotation_pivot; +#endif // ENABLE_CGAL_BOUNDING_SPHERE }; // Volumes owned by GLCanvas3D. @@ -150,6 +153,10 @@ private: // and transform to place and orient it in world coordinates std::optional> m_bounding_box_in_current_reference_system; +#if ENABLE_CGAL_BOUNDING_SPHERE + std::optional> m_bounding_sphere; +#endif // ENABLE_CGAL_BOUNDING_SPHERE + #if ENABLE_RENDER_SELECTION_CENTER GLModel m_vbo_sphere; #endif // ENABLE_RENDER_SELECTION_CENTER @@ -295,6 +302,11 @@ public: // Returns the screen space bounding box BoundingBoxf get_screen_space_bounding_box(); +#if ENABLE_CGAL_BOUNDING_SPHERE + // Returns the bounding sphere + const std::pair get_bounding_sphere() const; +#endif // ENABLE_CGAL_BOUNDING_SPHERE + void setup_cache(); void translate(const Vec3d& displacement, TransformationType transformation_type); @@ -360,6 +372,9 @@ private: m_full_unscaled_instance_bounding_box.reset(); m_full_scaled_instance_bounding_box.reset(); m_full_unscaled_instance_local_bounding_box.reset(); m_bounding_box_in_current_reference_system.reset(); +#if ENABLE_CGAL_BOUNDING_SPHERE + m_bounding_sphere.reset(); +#endif // ENABLE_CGAL_BOUNDING_SPHERE } void render_synchronized_volumes(); void render_bounding_box(const BoundingBoxf3& box, const Transform3d& trafo, const ColorRGB& color);