From f251ac5c7e86033016ac4184bd6d3ebbac4efc77 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Tue, 26 Apr 2022 22:05:01 +0200 Subject: [PATCH] Transform cuted surface on model --- src/libslic3r/CutSurface.cpp | 67 +++++++++++++++++++++++++ src/libslic3r/CutSurface.hpp | 15 ++++++ src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 52 +++++++++++-------- 3 files changed, 112 insertions(+), 22 deletions(-) diff --git a/src/libslic3r/CutSurface.cpp b/src/libslic3r/CutSurface.cpp index 0d4cd2aa15..1fc12eaee4 100644 --- a/src/libslic3r/CutSurface.cpp +++ b/src/libslic3r/CutSurface.cpp @@ -21,6 +21,13 @@ void Slic3r::append(SurfaceCut &sc, SurfaceCut &&sc_add) its_merge(sc, std::move(sc_add)); } +SurfaceCut Slic3r::merge(SurfaceCuts &&cuts) { + SurfaceCut result; + for (SurfaceCut &cut : cuts) + append(result, std::move(cut)); + return result; +} + #include #include #include @@ -555,6 +562,66 @@ indexed_triangle_set Slic3r::cuts2model(const SurfaceCuts &cuts, return result; } +indexed_triangle_set Slic3r::cut2model(const SurfaceCut &cut, + const Emboss::IProject &projection) +{ + assert(!cut.empty()); + size_t count_vertices = cut.vertices.size() * 2; + size_t count_indices = cut.indices.size() * 2; + + // indices from from zig zag + for (const auto &c : cut.contours) { + assert(!c.empty()); + count_indices += c.size() * 2; + } + + indexed_triangle_set result; + result.vertices.reserve(count_vertices); + result.indices.reserve(count_indices); + + // front + result.vertices.insert(result.vertices.end(), + cut.vertices.begin(), cut.vertices.end()); + result.indices.insert(result.indices.end(), + cut.indices.begin(), cut.indices.end()); + + // back + for (const auto &v : cut.vertices) { + Vec3f v2 = projection.project(v); + result.vertices.push_back(v2); + } + + size_t back_offset = cut.vertices.size(); + for (const auto &i : cut.indices) { + // check range of indices in cut + assert(i.x() >= 0 && i.x() < cut.vertices.size()); + assert(i.y() >= 0 && i.y() < cut.vertices.size()); + assert(i.z() >= 0 && i.z() < cut.vertices.size()); + // Y and Z is swapped CCW triangles for back side + result.indices.emplace_back(i.x() + back_offset, + i.z() + back_offset, + i.y() + back_offset); + } + + // zig zag indices + for (const auto &contour : cut.contours) { + size_t prev_front_index = contour.back(); + size_t prev_back_index = back_offset + prev_front_index; + for (size_t front_index : contour) { + assert(front_index < cut.vertices.size()); + size_t back_index = back_offset + front_index; + result.indices.emplace_back(front_index, prev_front_index, back_index); + result.indices.emplace_back(prev_front_index, prev_back_index, back_index); + prev_front_index = front_index; + prev_back_index = back_index; + } + } + + assert(count_vertices == result.vertices.size()); + assert(count_indices == result.indices.size()); + return result; +} + priv::CutMesh priv::to_cgal(const indexed_triangle_set &its) { CutMesh result; diff --git a/src/libslic3r/CutSurface.hpp b/src/libslic3r/CutSurface.hpp index 64d46fdd9f..0b65bccd2c 100644 --- a/src/libslic3r/CutSurface.hpp +++ b/src/libslic3r/CutSurface.hpp @@ -42,6 +42,12 @@ using SurfaceCuts = std::vector; /// Surface cut to consume void append(SurfaceCut &sc, SurfaceCut &&sc_add); +/// +/// Merge surface cuts int one +/// +/// input +SurfaceCut merge(SurfaceCuts&& cuts); + /// /// Cut surface shape from model. /// IMPROVE1: It is possible to prefiltrate model triangles befor cut.(AABB) @@ -63,6 +69,15 @@ SurfaceCuts cut_surface(const indexed_triangle_set &model, /// Mesh indexed_triangle_set cuts2model(const SurfaceCuts &cuts, const Emboss::IProject &projection); +/// +/// Create model from surface cuts by projection +/// +/// Surface from model with outlines +/// Way of emboss +/// Mesh +indexed_triangle_set cut2model(const SurfaceCut &cut, + const Emboss::IProject &projection); + } // namespace Slic3r #endif // slic3r_CutSurface_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index e682a50de7..033975961e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -1018,13 +1018,13 @@ std::unique_ptr create_projection_for_cut( /// True .. raise, False .. engrave /// Text configuration /// Text voliume transformation inside object -/// Cutted surfaces from model +/// Cutted surface from model /// Projection static std::unique_ptr create_emboss_projection( bool is_outside, const TextConfiguration &tc, - Transform3d tr, - SurfaceCuts &cuts) + Transform3d tr, + SurfaceCut &cut) { // Offset of clossed side to model const float surface_offset = 1e-3; // [in mm] @@ -1038,18 +1038,21 @@ static std::unique_ptr create_emboss_projection( front_move = surface_offset; back_move = -fp.emboss; } - Matrix3d rot = tr.rotation(); - - float z_dir = back_move - front_move; - Vec3f dir = (rot * Vec3d(0., 0., z_dir)).cast(); + Matrix3d rot_i = tr.rotation().inverse(); + its_transform(cut, rot_i); + BoundingBoxf3 bb = Slic3r::bounding_box(cut); + float z_move = -bb.max.z(); + float x_center = (bb.max.x() + bb.min.x()) / 2; + float y_center = (bb.max.y() + bb.min.y()) / 2; // move to front distance - Vec3f move = (rot * Vec3d(0., 0., front_move)).cast(); - for (SurfaceCut &cut : cuts) - its_translate(cut, move); - - // Transformation is not used - return std::make_unique(Transform3d::Identity(), dir); + Vec3f move(x_center, y_center, front_move + z_move); + + its_translate(cut, move); + + Vec3f from_front_to_back(0.f, 0.f, back_move - front_move); + return std::make_unique(Transform3d::Identity() /*not used*/, + from_front_to_back); } void GLGizmoEmboss::use_surface() { @@ -1084,25 +1087,30 @@ void GLGizmoEmboss::use_surface() { bool is_outside = m_volume->is_model_part(); assert(is_outside || m_volume->is_negative_volume() || m_volume->is_modifier()); - //Transform3d wanted_tr = ; + // apply only rotation to know BB center of result + Matrix3d rot = cut_projection_tr.rotation().inverse(); - // NOTE! - It needs to translate cuts - Transform3d tr = source->get_matrix().inverse() * input_tr; - auto projection = create_emboss_projection(is_outside, tc, tr, cuts); + SurfaceCut cut = merge(std::move(cuts)); + // NOTE! - Projection needs to transform cut + auto projection = create_emboss_projection(is_outside, tc, cut_projection_tr, cut); if (projection == nullptr) return; - indexed_triangle_set new_its = cuts2model(cuts, *projection); + indexed_triangle_set new_its = cut2model(cut, *projection); its_write_obj(new_its, "C:/data/temp/projected.obj"); // only debug TriangleMesh tm(std::move(new_its)); // center triangle mesh Vec3d shift = tm.bounding_box().center(); + // do not center in emboss direction + shift.z() = 0; tm.translate(-shift.cast()); - Transform3d trafo = Transform3d::Identity(); - trafo.translate(shift); - trafo = source->get_matrix() * trafo; - m_volume->set_transformation(trafo); + // discard fix transformation when exists + if (tc.fix_3mf_tr.has_value()) { + m_volume->set_transformation(input_tr); + m_volume->text_configuration->fix_3mf_tr = {}; + } + m_volume->set_mesh(std::move(tm)); m_volume->set_new_unique_id(); wxGetApp().plater()->canvas3D()->reload_scene(true);