Transform cuted surface on model
This commit is contained in:
parent
a1d7040902
commit
f251ac5c7e
3 changed files with 112 additions and 22 deletions
|
@ -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 <CGAL/Polygon_mesh_processing/corefinement.h>
|
||||
#include <CGAL/Exact_integer.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
|
@ -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;
|
||||
|
|
|
@ -42,6 +42,12 @@ using SurfaceCuts = std::vector<SurfaceCut>;
|
|||
/// <param name="sc_add">Surface cut to consume</param>
|
||||
void append(SurfaceCut &sc, SurfaceCut &&sc_add);
|
||||
|
||||
/// <summary>
|
||||
/// Merge surface cuts int one
|
||||
/// </summary>
|
||||
/// <param name="cuts">input</param>
|
||||
SurfaceCut merge(SurfaceCuts&& cuts);
|
||||
|
||||
/// <summary>
|
||||
/// 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,
|
|||
/// <returns>Mesh</returns>
|
||||
indexed_triangle_set cuts2model(const SurfaceCuts &cuts,
|
||||
const Emboss::IProject &projection);
|
||||
/// <summary>
|
||||
/// Create model from surface cuts by projection
|
||||
/// </summary>
|
||||
/// <param name="cut">Surface from model with outlines</param>
|
||||
/// <param name="projection">Way of emboss</param>
|
||||
/// <returns>Mesh</returns>
|
||||
indexed_triangle_set cut2model(const SurfaceCut &cut,
|
||||
const Emboss::IProject &projection);
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
#endif // slic3r_CutSurface_hpp_
|
||||
|
|
|
@ -1018,13 +1018,13 @@ std::unique_ptr<Emboss::IProject> create_projection_for_cut(
|
|||
/// <param name="is_outside">True .. raise, False .. engrave</param>
|
||||
/// <param name="tc">Text configuration</param>
|
||||
/// <param name="tr">Text voliume transformation inside object</param>
|
||||
/// <param name="cuts">Cutted surfaces from model</param>
|
||||
/// <param name="cut">Cutted surface from model</param>
|
||||
/// <returns>Projection</returns>
|
||||
static std::unique_ptr<Emboss::IProject> 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<Emboss::IProject> 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<float>();
|
||||
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<float>();
|
||||
for (SurfaceCut &cut : cuts)
|
||||
its_translate(cut, move);
|
||||
|
||||
// Transformation is not used
|
||||
return std::make_unique<Emboss::OrthoProject>(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<Emboss::OrthoProject>(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<float>());
|
||||
|
||||
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue