diff --git a/src/libslic3r/SLA/SLAAutoSupports.cpp b/src/libslic3r/SLA/SLAAutoSupports.cpp index 73c418911..ca04b1bee 100644 --- a/src/libslic3r/SLA/SLAAutoSupports.cpp +++ b/src/libslic3r/SLA/SLAAutoSupports.cpp @@ -92,7 +92,7 @@ void SLAAutoSupports::generate() Vec3f normal; int added_points = 0; int refused_points = 0; - const int refused_limit = std::min(100, (int)(1. / m_config.density_at_horizontal)); + const int refused_limit = 30; // Angle at which the density reaches zero: const float threshold_angle = std::min(M_PI_2, M_PI_4 * acos(0.f/m_config.density_at_horizontal) / acos(m_config.density_at_45/m_config.density_at_horizontal)); @@ -146,8 +146,8 @@ float SLAAutoSupports::get_required_density(float angle) const { // calculation would be density_0 * cos(angle). To provide one more degree of freedom, we will scale the angle // to get the user-set density for 45 deg. So it ends up as density_0 * cos(K * angle). - float K = 4*acos(m_config.density_at_45/m_config.density_at_horizontal) / M_PI; - return std::max(0., m_config.density_at_horizontal * cos(K*angle)); + float K = 4.f * float(acos(m_config.density_at_45/m_config.density_at_horizontal) / M_PI); + return std::max(0.f, float(m_config.density_at_horizontal * cos(K*angle))); } diff --git a/src/libslic3r/SLA/SLAAutoSupports.hpp b/src/libslic3r/SLA/SLAAutoSupports.hpp index 637f0909c..816fa6180 100644 --- a/src/libslic3r/SLA/SLAAutoSupports.hpp +++ b/src/libslic3r/SLA/SLAAutoSupports.hpp @@ -2,6 +2,8 @@ #define SLAAUTOSUPPORTS_HPP_ #include +#include + namespace Slic3r { diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index cef3eedd1..2bd3e2b2a 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -27,10 +27,13 @@ #define ENABLE_WORLD_ROTATIONS (1 && ENABLE_1_42_0) // Scene's GUI made using imgui library #define ENABLE_IMGUI (1 && ENABLE_1_42_0) +#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_IMGUI) // Modified Sla support gizmo #define ENABLE_SLA_SUPPORT_GIZMO_MOD (1 && ENABLE_1_42_0) // Removes the wxNotebook from plater #define ENABLE_REMOVE_TABS_FROM_PLATER (1 && ENABLE_1_42_0) +// Constrains the camera target into the scene bounding box +#define ENABLE_CONSTRAINED_CAMERA_TARGET (1 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1cb8622de..208516536 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -273,8 +273,13 @@ GLCanvas3D::Camera::Camera() , zoom(1.0f) , phi(45.0f) // , distance(0.0f) +#if !ENABLE_CONSTRAINED_CAMERA_TARGET , target(0.0, 0.0, 0.0) +#endif // !ENABLE_CONSTRAINED_CAMERA_TARGET , m_theta(45.0f) +#if ENABLE_CONSTRAINED_CAMERA_TARGET + , m_target(Vec3d::Zero()) +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET { } @@ -292,16 +297,32 @@ std::string GLCanvas3D::Camera::get_type_as_string() const }; } -float GLCanvas3D::Camera::get_theta() const -{ - return m_theta; -} - void GLCanvas3D::Camera::set_theta(float theta) { m_theta = clamp(0.0f, GIMBALL_LOCK_THETA_MAX, theta); } +#if ENABLE_CONSTRAINED_CAMERA_TARGET +void GLCanvas3D::Camera::set_target(const Vec3d& target, GLCanvas3D& canvas) +{ + m_target = target; + m_target(0) = clamp(m_scene_box.min(0), m_scene_box.max(0), m_target(0)); + m_target(1) = clamp(m_scene_box.min(1), m_scene_box.max(1), m_target(1)); + m_target(2) = clamp(m_scene_box.min(2), m_scene_box.max(2), m_target(2)); + if (!m_target.isApprox(target)) + canvas.viewport_changed(); +} + +void GLCanvas3D::Camera::set_scene_box(const BoundingBoxf3& box, GLCanvas3D& canvas) +{ + if (m_scene_box != box) + { + m_scene_box = box; + canvas.viewport_changed(); + } +} +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET + GLCanvas3D::Bed::Bed() : m_type(Custom) { @@ -3650,6 +3671,15 @@ BoundingBoxf3 GLCanvas3D::volumes_bounding_box() const return bb; } +#if ENABLE_CONSTRAINED_CAMERA_TARGET +BoundingBoxf3 GLCanvas3D::scene_bounding_box() const +{ + BoundingBoxf3 bb = volumes_bounding_box(); + bb.merge(m_bed.get_bounding_box()); + return bb; +} +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET + bool GLCanvas3D::is_layers_editing_enabled() const { return m_layers_editing.is_enabled(); @@ -3789,7 +3819,12 @@ void GLCanvas3D::set_viewport_from_scene(const GLCanvas3D& other) { m_camera.phi = other.m_camera.phi; m_camera.set_theta(other.m_camera.get_theta()); +#if ENABLE_CONSTRAINED_CAMERA_TARGET + m_camera.set_scene_box(other.m_camera.get_scene_box(), *this); + m_camera.set_target(other.m_camera.get_target(), *this); +#else m_camera.target = other.m_camera.target; +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET m_camera.zoom = other.m_camera.zoom; m_dirty = true; } @@ -4318,6 +4353,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // restore to default value m_regenerate_volumes = true; + +#if ENABLE_CONSTRAINED_CAMERA_TARGET + m_camera.set_scene_box(scene_bounding_box(), *this); + m_camera.set_target(m_camera.get_target(), *this); +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET + // and force this canvas to be redrawn. m_dirty = true; } @@ -4857,7 +4898,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) float z = 0.0f; const Vec3d& cur_pos = _mouse_to_3d(pos, &z); Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); +#if ENABLE_CONSTRAINED_CAMERA_TARGET + m_camera.set_target(m_camera.get_target() + orig - cur_pos, *this); +#else m_camera.target += orig - cur_pos; +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET viewport_changed(); @@ -4938,10 +4983,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #if ENABLE_WORLD_ROTATIONS _update_gizmos_data(); #endif // ENABLE_WORLD_ROTATIONS + wxGetApp().obj_manipul()->update_settings_value(m_selection); // Let the platter know that the dragging finished, so a delayed refresh // of the scene with the background processing data should be performed. post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); +#if ENABLE_CONSTRAINED_CAMERA_TARGET + m_camera.set_scene_box(scene_bounding_box(), *this); +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET } m_moving = false; @@ -5533,7 +5582,11 @@ void GLCanvas3D::_zoom_to_bounding_box(const BoundingBoxf3& bbox) { m_camera.zoom = zoom; // center view around bounding box center +#if ENABLE_CONSTRAINED_CAMERA_TARGET + m_camera.set_target(bbox.center(), *this); +#else m_camera.target = bbox.center(); +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET viewport_changed(); @@ -5655,7 +5708,12 @@ void GLCanvas3D::_camera_tranform() const ::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); // pitch ::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f); // yaw +#if ENABLE_CONSTRAINED_CAMERA_TARGET + Vec3d target = -m_camera.get_target(); + ::glTranslated(target(0), target(1), target(2)); +#else ::glTranslated(-m_camera.target(0), -m_camera.target(1), -m_camera.target(2)); +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET } void GLCanvas3D::_picking_pass() const @@ -5970,6 +6028,23 @@ void GLCanvas3D::_render_camera_target() const ::glLineWidth(2.0f); ::glBegin(GL_LINES); +#if ENABLE_CONSTRAINED_CAMERA_TARGET + const Vec3d& target = m_camera.get_target(); + // draw line for x axis + ::glColor3f(1.0f, 0.0f, 0.0f); + ::glVertex3d(target(0) - half_length, target(1), target(2)); + ::glVertex3d(target(0) + half_length, target(1), target(2)); + // draw line for y axis + ::glColor3f(0.0f, 1.0f, 0.0f); + ::glVertex3d(target(0), target(1) - half_length, target(2)); + ::glVertex3d(target(0), target(1) + half_length, target(2)); + ::glEnd(); + + ::glBegin(GL_LINES); + ::glColor3f(0.0f, 0.0f, 1.0f); + ::glVertex3d(target(0), target(1), target(2) - half_length); + ::glVertex3d(target(0), target(1), target(2) + half_length); +#else // draw line for x axis ::glColor3f(1.0f, 0.0f, 0.0f); ::glVertex3d(m_camera.target(0) - half_length, m_camera.target(1), m_camera.target(2)); @@ -5984,6 +6059,7 @@ void GLCanvas3D::_render_camera_target() const ::glColor3f(0.0f, 0.0f, 1.0f); ::glVertex3d(m_camera.target(0), m_camera.target(1), m_camera.target(2) - half_length); ::glVertex3d(m_camera.target(0), m_camera.target(1), m_camera.target(2) + half_length); +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET ::glEnd(); } #endif // ENABLE_SHOW_CAMERA_TARGET diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 837b83e8a..d43fff271 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -153,9 +153,15 @@ class GLCanvas3D float zoom; float phi; // float distance; +#if !ENABLE_CONSTRAINED_CAMERA_TARGET Vec3d target; +#endif !// ENABLE_CONSTRAINED_CAMERA_TARGET private: +#if ENABLE_CONSTRAINED_CAMERA_TARGET + Vec3d m_target; + BoundingBoxf3 m_scene_box; +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET float m_theta; public: @@ -163,8 +169,16 @@ class GLCanvas3D std::string get_type_as_string() const; - float get_theta() const; + float get_theta() const { return m_theta; } void set_theta(float theta); + +#if ENABLE_CONSTRAINED_CAMERA_TARGET + const Vec3d& get_target() const { return m_target; } + void set_target(const Vec3d& target, GLCanvas3D& canvas); + + const BoundingBoxf3& get_scene_box() const { return m_scene_box; } + void set_scene_box(const BoundingBoxf3& box, GLCanvas3D& canvas); +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET }; class Bed @@ -782,7 +796,9 @@ private: wxWindow *m_external_gizmo_widgets_parent; #endif // not ENABLE_IMGUI +#if !ENABLE_CONSTRAINED_CAMERA_TARGET void viewport_changed(); +#endif // !ENABLE_CONSTRAINED_CAMERA_TARGET public: GLCanvas3D(wxGLCanvas* canvas); @@ -845,6 +861,9 @@ public: float get_camera_zoom() const; BoundingBoxf3 volumes_bounding_box() const; +#if ENABLE_CONSTRAINED_CAMERA_TARGET + BoundingBoxf3 scene_bounding_box() const; +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET bool is_layers_editing_enabled() const; bool is_layers_editing_allowed() const; @@ -936,6 +955,10 @@ public: void update_gizmos_on_off_state(); +#if ENABLE_CONSTRAINED_CAMERA_TARGET + void viewport_changed(); +#endif // ENABLE_CONSTRAINED_CAMERA_TARGET + private: bool _is_shown_on_screen() const; void _force_zoom_to_bed(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 34de24983..119838dad 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -770,6 +770,7 @@ void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const #if ENABLE_IMGUI void GLGizmoRotate3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) { +#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle())); wxString label = _(L("Rotation (deg)")); @@ -778,6 +779,7 @@ void GLGizmoRotate3D::on_render_input_window(float x, float y, const GLCanvas3D: m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); m_imgui->input_vec3("", rotation, 100.0f, "%.2f"); m_imgui->end(); +#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI } #endif // ENABLE_IMGUI @@ -1074,6 +1076,7 @@ void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selectio #if ENABLE_IMGUI void GLGizmoScale3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) { +#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI bool single_instance = selection.is_single_full_instance(); wxString label = _(L("Scale (%)")); @@ -1082,6 +1085,7 @@ void GLGizmoScale3D::on_render_input_window(float x, float y, const GLCanvas3D:: m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); m_imgui->input_vec3("", m_scale * 100.f, 100.0f, "%.2f"); m_imgui->end(); +#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI } #endif // ENABLE_IMGUI @@ -1321,6 +1325,7 @@ void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection #if ENABLE_IMGUI void GLGizmoMove3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) { +#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI bool show_position = selection.is_single_full_instance(); const Vec3d& position = selection.get_bounding_box().center(); @@ -1333,6 +1338,7 @@ void GLGizmoMove3D::on_render_input_window(float x, float y, const GLCanvas3D::S m_imgui->input_vec3("", displacement, 100.0f, "%.2f"); m_imgui->end(); +#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI } #endif // ENABLE_IMGUI diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2a99d2c5c..bafa24aa0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -733,7 +733,7 @@ void Sidebar::show_info_sizer() auto& stats = model_object->volumes.front()->mesh.stl.stats; auto sf = model_instance->get_scaling_factor(); - p->object_info->info_volume->SetLabel(wxString::Format("%.2f", stats.volume * sf(0) * sf(1) * sf(2))); + p->object_info->info_volume->SetLabel(wxString::Format("%.2f", size(0) * size(1) * size(2) * sf(0) * sf(1) * sf(2))); p->object_info->info_facets->SetLabel(wxString::Format(_(L("%d (%d shells)")), static_cast(model_object->facets_count()), stats.number_of_parts)); int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +