Cut bug fixing:

* Fix for https://dev.prusa3d.com/browse/SPE-1489 - The text is misaligned in cut dialog.
* Fix for https://dev.prusa3d.com/browse/SPE-1382 - Cut Plane does not move smoothly for multipart models.
+ Code cleanup - unused code is removed.
This commit is contained in:
YuSanka 2023-02-16 16:22:56 +01:00
parent 30bae9f803
commit dc0275f70d
2 changed files with 30 additions and 54 deletions

View File

@ -244,7 +244,7 @@ std::string GLGizmoCut3D::get_tooltip() const
if (m_hover_id == Z || (m_dragging && m_hover_id == CutPlane)) { if (m_hover_id == Z || (m_dragging && m_hover_id == CutPlane)) {
double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0; double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0;
std::string unit_str = " " + (m_imperial_units ? _u8L("inch") : _u8L("mm")); std::string unit_str = " " + (m_imperial_units ? _u8L("inch") : _u8L("mm"));
const BoundingBoxf3 tbb = transformed_bounding_box(m_plane_center); const BoundingBoxf3& tbb = m_transformed_bounding_box;
if (tbb.max.z() >= 0.0) { if (tbb.max.z() >= 0.0) {
double top = (tbb.min.z() <= 0.0 ? tbb.max.z() : tbb.size().z()) * koef; double top = (tbb.min.z() <= 0.0 ? tbb.max.z() : tbb.size().z()) * koef;
tooltip += format(top, 2) + " " + unit_str + " (" + _u8L("Top part") + ")"; tooltip += format(top, 2) + " " + unit_str + " (" + _u8L("Top part") + ")";
@ -401,7 +401,7 @@ bool GLGizmoCut3D::is_looking_forward() const
void GLGizmoCut3D::update_clipper() void GLGizmoCut3D::update_clipper()
{ {
BoundingBoxf3 box = bounding_box(); BoundingBoxf3 box = m_bounding_box;
// update cut_normal // update cut_normal
Vec3d beg, end = beg = m_plane_center; Vec3d beg, end = beg = m_plane_center;
@ -549,7 +549,7 @@ bool GLGizmoCut3D::render_slider_double_input(const std::string& label, float& v
return !is_approx(old_val, value); return !is_approx(old_val, value);
}; };
const BoundingBoxf3 bbox = bounding_box(); const BoundingBoxf3 bbox = m_bounding_box;
const float mean_size = float((bbox.size().x() + bbox.size().y() + bbox.size().z()) / 9.0) * (m_imperial_units ? f_mm_to_in : 1.f); const float mean_size = float((bbox.size().x() + bbox.size().y() + bbox.size().z()) / 9.0) * (m_imperial_units ? f_mm_to_in : 1.f);
ImGuiWrapper::text(label); ImGuiWrapper::text(label);
@ -795,7 +795,7 @@ void GLGizmoCut3D::render_cut_plane_grabbers()
const Transform3d view_matrix = wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m; const Transform3d view_matrix = wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
const double mean_size = get_grabber_mean_size(bounding_box()); const double mean_size = get_grabber_mean_size(m_bounding_box);
double size; double size;
const bool dragging_by_cut_plane = m_dragging && m_hover_id == CutPlane; const bool dragging_by_cut_plane = m_dragging && m_hover_id == CutPlane;
@ -1033,7 +1033,7 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform()
else if (!cut_line_processing()){ else if (!cut_line_processing()){
const Transform3d trafo = translation_transform(m_plane_center) * m_rotation_m; const Transform3d trafo = translation_transform(m_plane_center) * m_rotation_m;
const BoundingBoxf3 box = bounding_box(); const BoundingBoxf3 box = m_bounding_box;
const double size = get_half_size(get_grabber_mean_size(box)); const double size = get_half_size(get_grabber_mean_size(box));
Vec3d scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size); Vec3d scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
@ -1183,7 +1183,11 @@ void GLGizmoCut3D::dragging_grabber_xy(const GLGizmoBase::UpdateData &data)
Vec3d rotation = Vec3d::Zero(); Vec3d rotation = Vec3d::Zero();
rotation[m_hover_id] = theta; rotation[m_hover_id] = theta;
m_rotation_m = m_start_dragging_m * rotation_transform(rotation);
const Transform3d rotation_tmp = m_start_dragging_m * rotation_transform(rotation);
if (m_rotation_m.rotation() != rotation_tmp.rotation())
m_transformed_bounding_box = transformed_bounding_box(m_plane_center);
m_rotation_m = rotation_tmp;
m_angle = theta; m_angle = theta;
while (m_angle > two_pi) while (m_angle > two_pi)
@ -1245,9 +1249,13 @@ void GLGizmoCut3D::on_stop_dragging()
void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool force/* = false*/) void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool force/* = false*/)
{ {
if (m_plane_center == center_pos)
return;
bool can_set_center_pos = force; bool can_set_center_pos = force;
BoundingBoxf3 tbb;
if (!can_set_center_pos) { if (!can_set_center_pos) {
const BoundingBoxf3 tbb = transformed_bounding_box(center_pos); tbb = transformed_bounding_box(center_pos);
if (tbb.max.z() > -1. && tbb.min.z() < 1.) if (tbb.max.z() > -1. && tbb.min.z() < 1.)
can_set_center_pos = true; can_set_center_pos = true;
else { else {
@ -1260,6 +1268,7 @@ void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool force/* = false*
} }
if (can_set_center_pos) { if (can_set_center_pos) {
m_transformed_bounding_box = tbb;
m_plane_center = center_pos; m_plane_center = center_pos;
m_center_offset = m_plane_center - m_bb_center; m_center_offset = m_plane_center - m_bb_center;
} }
@ -1279,7 +1288,7 @@ BoundingBoxf3 GLGizmoCut3D::bounding_box() const
return ret; return ret;
} }
BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center, bool revert_move /*= false*/) const BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center) const
{ {
// #ysFIXME !!! // #ysFIXME !!!
BoundingBoxf3 ret; BoundingBoxf3 ret;
@ -1299,10 +1308,7 @@ BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center,
Vec3d cut_center_offset = plane_center - instance_offset; Vec3d cut_center_offset = plane_center - instance_offset;
cut_center_offset[Z] -= sel_info->get_sla_shift(); cut_center_offset[Z] -= sel_info->get_sla_shift();
const auto move = translation_transform(-cut_center_offset); const auto cut_matrix = Transform3d::Identity() * m_rotation_m.inverse() * translation_transform(-cut_center_offset);
const auto move2 = translation_transform(plane_center);
const auto cut_matrix = (revert_move ? move2 : Transform3d::Identity()) * m_rotation_m.inverse() * move;
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
const Selection::IndicesList& idxs = selection.get_volume_idxs(); const Selection::IndicesList& idxs = selection.get_volume_idxs();
@ -1335,6 +1341,8 @@ bool GLGizmoCut3D::update_bb()
const BoundingBoxf3 box = bounding_box(); const BoundingBoxf3 box = bounding_box();
if (m_max_pos != box.max || m_min_pos != box.min) { if (m_max_pos != box.max || m_min_pos != box.min) {
m_bounding_box = box;
invalidate_cut_plane(); invalidate_cut_plane();
m_max_pos = box.max; m_max_pos = box.max;
@ -1388,7 +1396,7 @@ void GLGizmoCut3D::init_picking_models()
} }
if (!m_plane.model.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) { if (!m_plane.model.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) {
const double cp_width = 0.02 * get_grabber_mean_size(bounding_box()); const double cp_width = 0.02 * get_grabber_mean_size(m_bounding_box);
indexed_triangle_set its = its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4); indexed_triangle_set its = its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4);
m_plane.model.init_from(its); m_plane.model.init_from(its);
m_plane.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its))); m_plane.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
@ -1631,9 +1639,8 @@ void GLGizmoCut3D::render_build_size()
{ {
double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0; double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0;
wxString unit_str = " " + (m_imperial_units ? _L("in") : _L("mm")); wxString unit_str = " " + (m_imperial_units ? _L("in") : _L("mm"));
const BoundingBoxf3 tbb = transformed_bounding_box(m_plane_center);
Vec3d tbb_sz = tbb.size(); Vec3d tbb_sz = m_transformed_bounding_box.size();
wxString size = "X: " + double_to_string(tbb_sz.x() * koef, 2) + unit_str + wxString size = "X: " + double_to_string(tbb_sz.x() * koef, 2) + unit_str +
", Y: " + double_to_string(tbb_sz.y() * koef, 2) + unit_str + ", Y: " + double_to_string(tbb_sz.y() * koef, 2) + unit_str +
", Z: " + double_to_string(tbb_sz.z() * koef, 2) + unit_str; ", Z: " + double_to_string(tbb_sz.z() * koef, 2) + unit_str;
@ -1646,7 +1653,7 @@ void GLGizmoCut3D::render_build_size()
void GLGizmoCut3D::reset_cut_plane() void GLGizmoCut3D::reset_cut_plane()
{ {
set_center(bounding_box().center()); set_center(m_bb_center);
m_rotation_m = Transform3d::Identity(); m_rotation_m = Transform3d::Identity();
m_angle_arc.reset(); m_angle_arc.reset();
update_clipper(); update_clipper();
@ -1746,7 +1753,7 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
const bool has_connectors = !connectors.empty(); const bool has_connectors = !connectors.empty();
const bool is_cut_plane_init = m_rotation_m.isApprox(Transform3d::Identity()) && bounding_box().center() == m_plane_center; const bool is_cut_plane_init = m_rotation_m.isApprox(Transform3d::Identity()) && m_bb_center == m_plane_center;
m_imgui->disabled_begin(is_cut_plane_init); m_imgui->disabled_begin(is_cut_plane_init);
if (render_reset_button("cut_plane", _u8L("Reset cutting plane"))) if (render_reset_button("cut_plane", _u8L("Reset cutting plane")))
reset_cut_plane(); reset_cut_plane();
@ -1838,10 +1845,9 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
add_vertical_scaled_interval(0.75f); add_vertical_scaled_interval(0.75f);
m_imgui->disabled_begin(has_connectors); m_imgui->disabled_begin(has_connectors);
add_horizontal_shift(m_imgui->scaled(/*1*/.2f));
ImGuiWrapper::text(_L("Cut to") + ":"); ImGuiWrapper::text(_L("Cut to") + ":");
ImGui::SameLine(); add_horizontal_scaled_interval(1.2f);
if (m_imgui->radio_button(_L("Objects"), !m_keep_as_parts)) if (m_imgui->radio_button(_L("Objects"), !m_keep_as_parts))
m_keep_as_parts = false; m_keep_as_parts = false;
ImGui::SameLine(); ImGui::SameLine();
@ -1990,38 +1996,6 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
render_debug_input_window(x); render_debug_input_window(x);
} }
// get volume transformation regarding to the "border". Border is related from the size of connectors
Transform3d GLGizmoCut3D::get_volume_transformation(const ModelVolume* volume) const
{
bool is_prizm_dowel = m_connector_type == CutConnectorType::Dowel && m_connector_style == size_t(CutConnectorStyle::Prizm);
#if ENABLE_WORLD_COORDINATE
const Transform3d connector_trafo = is_prizm_dowel ?
Geometry::translation_transform(-m_connector_depth_ratio * Vec3d::UnitZ()) * m_rotation_m * Geometry::scale_transform({ 0.5 * m_connector_size, 0.5 * m_connector_size, 2 * m_connector_depth_ratio }) :
m_rotation_m * Geometry::scale_transform({ 0.5 * m_connector_size, 0.5 * m_connector_size, m_connector_depth_ratio });
#else
const Transform3d connector_trafo = assemble_transform(
is_prizm_dowel ? Vec3d(0.0, 0.0, -m_connector_depth_ratio) : Vec3d::Zero(),
Transformation(m_rotation_m).get_rotation(),
Vec3d(0.5*m_connector_size, 0.5*m_connector_size, is_prizm_dowel ? 2 * m_connector_depth_ratio : m_connector_depth_ratio),
Vec3d::Ones());
#endif // ENABLE_WORLD_COORDINATE
const Vec3d connector_bb = m_connector_mesh.transformed_bounding_box(connector_trafo).size();
const Vec3d bb = volume->mesh().bounding_box().size();
// calculate an unused border - part of the the volume, where we can't put connectors
const Vec3d border_scale(connector_bb.x() / bb.x(), connector_bb.y() / bb.y(), connector_bb.z() / bb.z());
const Transform3d vol_matrix = volume->get_matrix();
const Vec3d vol_trans = vol_matrix.translation();
// offset of the volume will be changed after scaling, so calculate the needed offset and set it to a volume_trafo
const Vec3d offset(vol_trans.x() * border_scale.x(), vol_trans.y() * border_scale.y(), vol_trans.z() * border_scale.z());
// scale and translate volume to suppress to put connectors too close to the border
return translation_transform(offset) * scale_transform(Vec3d::Ones() - border_scale) * vol_matrix;
}
bool GLGizmoCut3D::is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos) bool GLGizmoCut3D::is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos)
{ {
// check if connector pos is out of clipping plane // check if connector pos is out of clipping plane
@ -2072,7 +2046,7 @@ bool GLGizmoCut3D::is_conflict_for_connector(size_t idx, const CutConnectors& co
const BoundingBoxf3 cur_tbb = m_shapes[cur_connector.attribs].model.get_bounding_box().transformed(matrix); const BoundingBoxf3 cur_tbb = m_shapes[cur_connector.attribs].model.get_bounding_box().transformed(matrix);
// check if connector's bounding box is inside the object's bounding box // check if connector's bounding box is inside the object's bounding box
if (!bounding_box().contains(cur_tbb)) { if (!m_bounding_box.contains(cur_tbb)) {
m_info_stats.outside_bb++; m_info_stats.outside_bb++;
return true; return true;
} }

View File

@ -43,6 +43,9 @@ class GLGizmoCut3D : public GLGizmoBase
Vec3d m_bb_center{ Vec3d::Zero() }; Vec3d m_bb_center{ Vec3d::Zero() };
Vec3d m_center_offset{ Vec3d::Zero() }; Vec3d m_center_offset{ Vec3d::Zero() };
BoundingBoxf3 m_bounding_box;
BoundingBoxf3 m_transformed_bounding_box;
// values from RotationGizmo // values from RotationGizmo
double m_radius{ 0.0 }; double m_radius{ 0.0 };
double m_grabber_radius{ 0.0 }; double m_grabber_radius{ 0.0 };
@ -193,7 +196,7 @@ public:
void invalidate_cut_plane(); void invalidate_cut_plane();
BoundingBoxf3 bounding_box() const; BoundingBoxf3 bounding_box() const;
BoundingBoxf3 transformed_bounding_box(const Vec3d& plane_center, bool revert_move = false) const; BoundingBoxf3 transformed_bounding_box(const Vec3d& plane_center) const;
protected: protected:
bool on_init() override; bool on_init() override;
@ -263,7 +266,6 @@ private:
void render_connect_mode_radio_button(CutConnectorMode mode); void render_connect_mode_radio_button(CutConnectorMode mode);
bool render_reset_button(const std::string& label_id, const std::string& tooltip) const; bool render_reset_button(const std::string& label_id, const std::string& tooltip) const;
bool render_connect_type_radio_button(CutConnectorType type); bool render_connect_type_radio_button(CutConnectorType type);
Transform3d get_volume_transformation(const ModelVolume* volume) const;
bool is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos); bool is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos);
bool is_conflict_for_connector(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos); bool is_conflict_for_connector(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos);
void render_connectors(); void render_connectors();