From 10f07d881010ad45c70337f3e1536615834ad8f0 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Fri, 29 Apr 2022 19:53:02 +0200 Subject: [PATCH] Cutting shape mesh is over whole object. Infinite projection VRT object dimension --- src/libslic3r/CutSurface.cpp | 30 ++++++++-- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 80 ++++++++++++++----------- 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/src/libslic3r/CutSurface.cpp b/src/libslic3r/CutSurface.cpp index 1fc12eaee..2b047af4d 100644 --- a/src/libslic3r/CutSurface.cpp +++ b/src/libslic3r/CutSurface.cpp @@ -847,7 +847,13 @@ void priv::flood_fill_inner(const CutMesh &mesh, // list of other not constrained neighbors std::queue queue; do { - FI fi_opposite = mesh.face(mesh.opposite(hi)); + HI hi_opposite = mesh.opposite(hi); + // open edge doesn't have opposit half edge + if (!hi_opposite.is_valid()) { + hi = mesh.next(hi); + continue; + } + FI fi_opposite = mesh.face(hi_opposite); FaceType side = face_type_map[fi_opposite]; if (side == FaceType::inside) { has_inside_neighbor = true; @@ -872,8 +878,14 @@ void priv::flood_fill_inner(const CutMesh &mesh, HI hi = mesh.halfedge(fi); HI hi_end = hi; do { - FI fi_opposite = mesh.face(mesh.opposite(hi)); - FaceType& side = face_type_map[fi_opposite]; + HI hi_opposite = mesh.opposite(hi); + // open edge doesn't have opposit half edge + if (!hi_opposite.is_valid()) { + hi = mesh.next(hi); + continue; + } + FI fi_opposite = mesh.face(hi_opposite); + FaceType &side = face_type_map[fi_opposite]; if (side == FaceType::not_constrained) { if (is_toward_projection(fi_opposite, mesh, projection)) { queue.emplace(fi_opposite); @@ -970,7 +982,13 @@ void priv::collect_surface_data(std::queue &process, HI hi = mesh.halfedge(fi_); HI hi_end = hi; do { - FI fi_opposite = mesh.face(mesh.opposite(hi)); + HI hi_opposite = mesh.opposite(hi); + // open edge doesn't have opposit half edge + if (!hi_opposite.is_valid()) { + hi = mesh.next(hi); + continue; + } + FI fi_opposite = mesh.face(hi_opposite); FaceType side = face_type_map[fi_opposite]; if (side == FaceType::inside) { process.emplace(fi_opposite); @@ -1319,7 +1337,9 @@ void priv::filter_cuts(CutAOIs &cuts, } if (ci.cut_index == cut_index) { - assert(ci.vi == vi); + // In one connected triangles area are more points + // with same source point from text contour + //assert(ci.vi == vi); return false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 033975961..f8b5f80f9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -966,15 +966,6 @@ const ModelVolume *get_source_volume(const ModelVolume *text_volume) return nullptr; } -// search area range for cut surface -struct SurfaceConfig -{ - // zero is after move on surface + depth move - float min = -10.f; // [in mm] - float max = 100.f;// [in mm] -}; -static SurfaceConfig surface_cfg; - double get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff) { const auto &cn = fp.collection_number; @@ -991,24 +982,41 @@ double get_shape_scale(const FontProp &fp, const Emboss::FontFile &ff) /// Volume transformation in object /// Configuration of embossig /// Font file for size --> unit per em -/// Bounding box of shape to center result volume +/// Bounding box 2d of shape to center result volume +/// Bounding box 3d of model volume for projection ranges /// Orthogonal cut_projection std::unique_ptr create_projection_for_cut( Transform3d tr, const TextConfiguration &tc, const Emboss::FontFile &ff, - const BoundingBox shape_bb) -{ - double z_dir = -(surface_cfg.max - surface_cfg.min); - Vec3f dir = (tr * Vec3d(0., 0., z_dir)).cast(); + const BoundingBox &shape_bb, + const std::pair& z_range) +{ + // create sure that emboss object is bigger than source object + const float safe_extension = 1.0f; + float min_z = z_range.first - safe_extension; + float max_z = z_range.second + safe_extension; + assert(min_z < max_z); + // range between min and max value + double projection_size = max_z - min_z; + Matrix3d transformation_for_vector = tr.linear(); + // Projection must be negative value. + // System of text coordinate + // X .. from left to right + // Y .. from bottom to top + // Z .. from text to eye + Vec3d untransformed_direction(0., 0., -projection_size); + Vec3f project_direction = + (transformation_for_vector * untransformed_direction).cast(); + + // Projection is in direction from far plane + tr.translate(Vec3d(0., 0., max_z)); tr.scale(get_shape_scale(tc.font_item.prop, ff)); - - // Text aligmnemnt to center 2D + // Text alignemnt to center 2D Vec2d move = -(shape_bb.max + shape_bb.min).cast() / 2.; - tr.translate(Vec3d(move.x(), move.y(), -surface_cfg.min)); - - return std::make_unique(tr, dir); + tr.translate(Vec3d(move.x(), move.y(), 0.)); + return std::make_unique(tr, project_direction); } #include "libslic3r/CutSurface.hpp" @@ -1038,7 +1046,7 @@ static std::unique_ptr create_emboss_projection( front_move = surface_offset; back_move = -fp.emboss; } - Matrix3d rot_i = tr.rotation().inverse(); + Matrix3d rot_i = tr.linear().inverse(); its_transform(cut, rot_i); BoundingBoxf3 bb = Slic3r::bounding_box(cut); @@ -1056,9 +1064,11 @@ static std::unique_ptr create_emboss_projection( } void GLGizmoEmboss::use_surface() { + // Model to cut surface from. const ModelVolume *source = get_source_volume(m_volume); if (source == nullptr) return; + // font face with glyph cache auto ffc = m_font_manager.get_font().font_file_with_cache; if (!ffc.has_value()) return; @@ -1072,13 +1082,21 @@ void GLGizmoEmboss::use_surface() { BoundingBox bb = get_extents(shapes); - Transform3d input_tr = m_volume->get_matrix(); + Transform3d text_tr = m_volume->get_matrix(); if (tc.fix_3mf_tr.has_value()) - input_tr = input_tr * tc.fix_3mf_tr->inverse(); - Transform3d cut_projection_tr = source->get_matrix().inverse() * input_tr; + text_tr = text_tr * tc.fix_3mf_tr->inverse(); + + Transform3d source_tr = source->get_matrix(); + Transform3d source_tr_inv = source_tr.inverse(); + Transform3d cut_projection_tr = source_tr_inv * text_tr; + //Transform3d cut_projection_tr = source_tr * text_tr.inverse(); + + BoundingBoxf3 source_bb = source->mesh().bounding_box(); + BoundingBoxf3 source_bb_tr = source_bb.transformed(cut_projection_tr.inverse()); + std::pair z_range{source_bb_tr.min.z(), source_bb_tr.max.z()}; const Emboss::FontFile &ff = *ffc.font_file; - auto cut_projection = create_projection_for_cut(cut_projection_tr, tc, ff, bb); + auto cut_projection = create_projection_for_cut(cut_projection_tr, tc, ff, bb, z_range); if (cut_projection == nullptr) return; SurfaceCuts cuts = cut_surface(source->mesh().its, shapes, *cut_projection); @@ -1087,11 +1105,8 @@ void GLGizmoEmboss::use_surface() { bool is_outside = m_volume->is_model_part(); assert(is_outside || m_volume->is_negative_volume() || m_volume->is_modifier()); - // apply only rotation to know BB center of result - Matrix3d rot = cut_projection_tr.rotation().inverse(); - SurfaceCut cut = merge(std::move(cuts)); - // NOTE! - Projection needs to transform cut + // !! Projection needs to transform cut auto projection = create_emboss_projection(is_outside, tc, cut_projection_tr, cut); if (projection == nullptr) return; @@ -1107,7 +1122,7 @@ void GLGizmoEmboss::use_surface() { // discard fix transformation when exists if (tc.fix_3mf_tr.has_value()) { - m_volume->set_transformation(input_tr); + m_volume->set_transformation(text_tr); m_volume->text_configuration->fix_3mf_tr = {}; } @@ -1165,13 +1180,6 @@ void GLGizmoEmboss::draw_window() if (ImGui::Button(_u8L("UseSurface").c_str())) use_surface(); - ImGui::SameLine(); - ImGui::SetNextItemWidth(150); - ImGui::InputFloat("##min_cut", &surface_cfg.min); - ImGui::SameLine(); - ImGui::SetNextItemWidth(150); - ImGui::InputFloat("##max_cut", &surface_cfg.max); - // Option to create text volume when reselecting volumes m_imgui->disabled_begin(!exist_font_file); if (m_volume == nullptr) {