From 36810134cbbe6d0a6f56db6558ef23315f7955cc Mon Sep 17 00:00:00 2001 From: Mack Date: Wed, 30 Apr 2025 18:19:16 +0800 Subject: [PATCH] FIX:Brim ears support following the movement of the volume jira: STUDIO-11415 Change-Id: I5c7913e86a8dba597bd721f9f2ceae596a7b328b --- src/libslic3r/Brim.cpp | 7 ++++-- src/libslic3r/BrimEarsPoint.hpp | 8 +++++-- src/slic3r/GUI/GUI_ObjectList.cpp | 12 +++++++--- src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp | 29 +++++++++++++++++------ src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp | 2 +- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index 988dce63b..4bd7836b6 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -817,7 +817,10 @@ static ExPolygons make_brim_ears(const PrintObject* object, const double& flowWi const Point ¢er_offset = object->center_offset(); model_trsf = model_trsf.pretranslate(Vec3d(- unscale(center_offset.x()), - unscale(center_offset.y()), 0)); for (auto &pt : brim_ear_points) { - Vec3f world_pos = pt.transform(trsf.get_matrix()); + Transform3d v_trsf = Transform3d::Identity(); + if (pt.volume_idx > -1) + v_trsf = object->model_object()->volumes[pt.volume_idx]->get_matrix(); + Vec3f world_pos = pt.transform(trsf.get_matrix() * v_trsf); if ( world_pos.z() > 0) continue; Polygon point_round; float brim_width = floor(scale_(pt.head_front_radius) / flowWidth / 2) * flowWidth * 2; @@ -832,7 +835,7 @@ static ExPolygons make_brim_ears(const PrintObject* object, const double& flowWi } mouse_ears_ex.emplace_back(); mouse_ears_ex.back().contour = point_round; - Vec3f pos = pt.transform(model_trsf); + Vec3f pos = pt.transform(model_trsf * v_trsf); int32_t pt_x = scale_(pos.x()); int32_t pt_y = scale_(pos.y()); mouse_ears_ex.back().contour.translate(Point(pt_x, pt_y)); diff --git a/src/libslic3r/BrimEarsPoint.hpp b/src/libslic3r/BrimEarsPoint.hpp index a859d54f2..6734c2f38 100644 --- a/src/libslic3r/BrimEarsPoint.hpp +++ b/src/libslic3r/BrimEarsPoint.hpp @@ -18,6 +18,7 @@ struct BrimPoint { Vec3f pos; float head_front_radius; + int volume_idx; BrimPoint() : pos(Vec3f::Zero()), head_front_radius(0.f) @@ -26,14 +27,17 @@ struct BrimPoint BrimPoint(float pos_x, float pos_y, float pos_z, - float head_radius) + float head_radius, + int volume_idx = -1) : pos(pos_x, pos_y, pos_z) , head_front_radius(head_radius) + , volume_idx(volume_idx) {} - BrimPoint(Vec3f position, float head_radius) + BrimPoint(Vec3f position, float head_radius, int volume_idx = -1) : pos(position) , head_front_radius(head_radius) + , volume_idx(volume_idx) {} Vec3f transform(const Transform3d &trsf) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 5768cb2ed..d9bda6f09 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -3124,7 +3124,10 @@ void ObjectList::merge(bool to_multipart_object) // merge brim ears BrimPoints temp_brim_points = object->brim_points; for(auto& p : temp_brim_points) { - p.set_transform(transformation_matrix); + Transform3d v_matrix = Transform3d::Identity(); + if (p.volume_idx >= 0) + v_matrix = object->volumes[p.volume_idx]->get_matrix(); + p.set_transform(transformation_matrix * v_matrix); new_object->brim_points.push_back(p); } } @@ -3137,10 +3140,13 @@ void ObjectList::merge(bool to_multipart_object) //BBS init asssmble transformation Geometry::Transformation new_object_trsf = new_object->instances[0]->get_transformation(); new_object->instances[0]->set_assemble_transformation(new_object_trsf); - + // merge brim ears const Transform3d& new_object_inverse_matrix = new_object_trsf.get_matrix().inverse(); for (auto& p : new_object->brim_points) { - p.set_transform(new_object_inverse_matrix); + Transform3d v_matrix_inverse = Transform3d::Identity(); + if (p.volume_idx >= 0) + v_matrix_inverse = new_object->volumes[p.volume_idx]->get_matrix().inverse(); + p.set_transform(new_object_inverse_matrix * v_matrix_inverse); } //BBS: notify it before remove notify_instance_updated(m_objects->size() - 1); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp index 1446c99e0..ded794ab0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp @@ -122,6 +122,7 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); const Transform3d& view_matrix = camera.get_view_matrix(); const Transform3d& projection_matrix = camera.get_projection_matrix(); + Transform3d volume_matrix = Transform3d::Identity(); shader->set_uniform("projection_matrix", projection_matrix); @@ -133,6 +134,9 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co const bool &error = editing_cache[i].is_error; if (!is_use_point(brim_point) && !hover) continue; + if (brim_point.volume_idx >= 0) + volume_matrix = selection.get_volume(brim_point.volume_idx)->get_volume_transformation().get_matrix(); + // keep show brim ear // if (is_mesh_point_clipped(brim_point.pos.cast())) // continue; @@ -163,7 +167,7 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co if (shader && !picking) shader->set_uniform("emission_factor", 0.5f); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - const Transform3d brim_matrix = Geometry::assemble_transform(brim_point.pos.cast()) * instance_scaling_matrix_inverse; + const Transform3d brim_matrix = Geometry::assemble_transform(brim_point.pos.cast()) * instance_scaling_matrix_inverse * volume_matrix; if (vol->is_left_handed()) glFrontFace(GL_CW); @@ -309,7 +313,10 @@ bool GLGizmoBrimEars::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_p Transform3d inverse_trsf = volume->get_instance_transformation().get_matrix(true).inverse(); std::pair pos_and_normal; if (unproject_on_mesh2(mouse_position, pos_and_normal)) { - render_hover_point = CacheEntry(BrimPoint(pos_and_normal.first, m_new_point_head_diameter / 2.f), false, (inverse_trsf * m_world_normal).cast(), true); + int volume_idx = m_last_hit_volume->volume_idx(); + Transform3d v_trsf = selection.get_volume(volume_idx)->get_volume_transformation().get_matrix(); + Vec3d set_volume_trsf_pos = v_trsf.inverse() * pos_and_normal.first.cast(); + render_hover_point = CacheEntry(BrimPoint(set_volume_trsf_pos.cast(), m_new_point_head_diameter / 2.f, volume_idx), false, (inverse_trsf * m_world_normal).cast(), true); } else { render_hover_point.reset(); } @@ -338,17 +345,19 @@ bool GLGizmoBrimEars::gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_p std::pair pos_and_normal; if (unproject_on_mesh2(mouse_position, pos_and_normal)) { // we got an intersection + int volume_idx = m_last_hit_volume->volume_idx(); const Selection &selection = m_parent.get_selection(); const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); Transform3d trsf = volume->get_instance_transformation().get_matrix(); Transform3d inverse_trsf = volume->get_instance_transformation().get_matrix(true).inverse(); + Transform3d v_trsf = selection.get_volume(volume_idx)->get_volume_transformation().get_matrix(); // BBS brim ear postion is placed on the bottom side Vec3d world_pos = trsf * pos_and_normal.first.cast(); world_pos[2] = -0.0001; - Vec3d object_pos = trsf.inverse() * world_pos; + Vec3d object_pos = trsf.inverse() * v_trsf.inverse() * world_pos; // brim ear always face up Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Add brim ear"); - add_point_to_cache(object_pos.cast(), m_new_point_head_diameter / 2.f, false, (inverse_trsf * m_world_normal).cast()); + add_point_to_cache(object_pos.cast(), m_new_point_head_diameter / 2.f, false, (inverse_trsf * m_world_normal).cast(), volume_idx); m_parent.set_as_dirty(); m_wait_for_up_event = true; find_single(); @@ -982,9 +991,9 @@ void GLGizmoBrimEars::get_detection_radius_max() } } -bool GLGizmoBrimEars::add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal) +bool GLGizmoBrimEars::add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal, int volume_idx) { - BrimPoint point(pos, head_radius); + BrimPoint point(pos, head_radius, volume_idx); for (int i = 0; i < m_editing_cache.size(); i++) { if (m_editing_cache[i].brim_point == point) { return false; } } @@ -1055,7 +1064,6 @@ void GLGizmoBrimEars::find_single() } const Selection &selection = m_parent.get_selection(); const GLVolume *volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Geometry::Transformation trsf = volume->get_instance_transformation(); ExPolygons model_pl = m_first_layer; m_single_brim.clear(); @@ -1071,6 +1079,13 @@ void GLGizmoBrimEars::find_single() } auto end = --m_single_brim.end(); for (auto it = m_single_brim.begin(); it != m_single_brim.end(); ++it) { + int volume_idx = it->second.brim_point.volume_idx; + Geometry::Transformation trsf = volume->get_instance_transformation(); + if (volume_idx >= 0){ + const Geometry::Transformation v_trsf = selection.get_volume(volume_idx)->get_volume_transformation(); + trsf = trsf * v_trsf; + } + ExPolygon point_pl = make_polygon(it->second.brim_point, trsf); if (overlaps(model_pl, point_pl)) { model_pl.emplace_back(point_pl); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp index f63ba8e34..eaebf3fbd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp @@ -164,7 +164,7 @@ protected: void register_single_mesh_pick(); void update_single_mesh_pick(GLVolume* v); void reset_all_pick(); - bool add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal); + bool add_point_to_cache(Vec3f pos, float head_radius, bool selected, Vec3f normal, int volume_idx=-1); float get_brim_default_radius() const; ExPolygon make_polygon(BrimPoint point, const Geometry::Transformation &trsf); void find_single();