From 15b13405141ca7481f156d204a917fab38c30dc1 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 4 Sep 2018 14:42:14 +0200 Subject: [PATCH] Added ModelInstance::world_matrix() method and stl_transform using eigen transform --- lib/Slic3r/GUI/Plater.pm | 5 +-- xs/src/admesh/stl.h | 1 + xs/src/admesh/util.cpp | 41 ++++++++++++++++++ xs/src/libslic3r/Model.cpp | 70 ++++++++++++++----------------- xs/src/libslic3r/Model.hpp | 2 + xs/src/libslic3r/TriangleMesh.cpp | 9 +++- xs/src/libslic3r/TriangleMesh.hpp | 1 + xs/src/slic3r/GUI/GLGizmo.cpp | 6 +-- 8 files changed, 89 insertions(+), 46 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 00267fe63..ce9e0da68 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1141,13 +1141,12 @@ sub rotate { } # Let's calculate vector of rotation axis (if we don't have it already) - # The minus is there so that the direction is the same as was established if (defined $axis) { if ($axis == X) { - $axis_x = -1; + $axis_x = 1; } if ($axis == Y) { - $axis_y = -1; + $axis_y = 1; } } diff --git a/xs/src/admesh/stl.h b/xs/src/admesh/stl.h index 5f7a3c5c1..096430d15 100644 --- a/xs/src/admesh/stl.h +++ b/xs/src/admesh/stl.h @@ -173,6 +173,7 @@ extern void stl_mirror_xy(stl_file *stl); extern void stl_mirror_yz(stl_file *stl); extern void stl_mirror_xz(stl_file *stl); extern void stl_transform(stl_file *stl, float *trafo3x4); +extern void stl_transform(stl_file *stl, const Eigen::Transform& t); extern void stl_open_merge(stl_file *stl, char *file); extern void stl_invalidate_shared_vertices(stl_file *stl); extern void stl_generate_shared_vertices(stl_file *stl); diff --git a/xs/src/admesh/util.cpp b/xs/src/admesh/util.cpp index fba1ee76b..cc104fdd1 100644 --- a/xs/src/admesh/util.cpp +++ b/xs/src/admesh/util.cpp @@ -155,6 +155,47 @@ void stl_transform(stl_file *stl, float *trafo3x4) { calculate_normals(stl); } +void stl_transform(stl_file *stl, const Eigen::Transform& t) +{ + if (stl->error) + return; + + unsigned int vertices_count = 3 * (unsigned int)stl->stats.number_of_facets; + if (vertices_count == 0) + return; + + Eigen::MatrixXf src_vertices(3, vertices_count); + stl_facet* facet_ptr = stl->facet_start; + unsigned int v_id = 0; + while (facet_ptr < stl->facet_start + stl->stats.number_of_facets) + { + for (int i = 0; i < 3; ++i) + { + ::memcpy((void*)src_vertices.col(v_id).data(), (const void*)&facet_ptr->vertex[i], 3 * sizeof(float)); + ++v_id; + } + facet_ptr += 1; + } + + Eigen::MatrixXf dst_vertices(3, vertices_count); + dst_vertices = t * src_vertices.colwise().homogeneous(); + + facet_ptr = stl->facet_start; + v_id = 0; + while (facet_ptr < stl->facet_start + stl->stats.number_of_facets) + { + for (int i = 0; i < 3; ++i) + { + ::memcpy((void*)&facet_ptr->vertex[i], (const void*)dst_vertices.col(v_id).data(), 3 * sizeof(float)); + ++v_id; + } + facet_ptr += 1; + } + + stl_get_size(stl); + calculate_normals(stl); +} + void stl_rotate_x(stl_file *stl, float angle) { int i; diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 1cd3b1413..36c210844 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -672,20 +672,18 @@ void ModelObject::center_around_origin() // First align to origin on XYZ, then center it on XY. Vec3d size = bb.size(); - size(2) = 0.; - Vec3d shift3 = - bb.min - 0.5 * size; - // Unaligned vector, for the Rotation2D to work on Visual Studio 2013. - Eigen::Vector2d shift2 = to_2d(shift3); - - this->translate(shift3); - this->origin_translation += shift3; - + size(2) = 0.0; + Vec3d shift = -bb.min - 0.5 * size; + + this->translate(shift); + this->origin_translation += shift; + if (!this->instances.empty()) { for (ModelInstance *i : this->instances) { // apply rotation and scaling to vector as well before translating instance, // in order to leave final position unaltered - Eigen::Rotation2Dd rot(i->rotation); - i->offset -= rot * shift2 * i->scaling_factor; + Vec3d i_shift = i->world_matrix(true) * shift; + i->offset -= to_2d(i_shift); } this->invalidate_bounding_box(); } @@ -861,12 +859,7 @@ void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_ { for (ModelInstance* inst : this->instances) { - Transform3d m = Transform3d::Identity(); - m.translate(Vec3d(inst->offset(0), inst->offset(1), 0.0)); - m.rotate(Eigen::AngleAxisd(inst->rotation, Vec3d::UnitZ())); - m.scale(inst->scaling_factor); - - BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(m); + BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(inst->world_matrix()); if (print_volume.contains(bb)) inst->print_volume_state = ModelInstance::PVS_Inside; @@ -995,26 +988,17 @@ size_t ModelVolume::split(unsigned int max_extruders) void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const { - mesh->rotate_z(this->rotation); // rotate around mesh origin - mesh->scale(this->scaling_factor); // scale around mesh origin - if (!dont_translate) - mesh->translate(this->offset(0), this->offset(1), 0); + mesh->transform(world_matrix(dont_translate).cast()); } BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate) const { // Rotate around mesh origin. - double c = cos(this->rotation); - double s = sin(this->rotation); - BoundingBoxf3 bbox; - for (int i = 0; i < mesh->stl.stats.number_of_facets; ++ i) { - const stl_facet &facet = mesh->stl.facet_start[i]; - for (int j = 0; j < 3; ++ j) { - const stl_vertex &v = facet.vertex[j]; - bbox.merge(Vec3d(c * v(0) - s * v(1), s * v(0) + c * v(1), v(2))); - } - } - if (! empty(bbox)) { + TriangleMesh copy(*mesh); + copy.transform(world_matrix(dont_translate, false, true).cast()); + BoundingBoxf3 bbox = copy.bounding_box(); + + if (!empty(bbox)) { // Scale the bounding box uniformly. if (std::abs(this->scaling_factor - 1.) > EPSILON) { bbox.min *= this->scaling_factor; @@ -1031,13 +1015,7 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const { - Transform3d matrix = Transform3d::Identity(); - if (!dont_translate) - matrix.translate(Vec3d(offset(0), offset(1), 0.0)); - - matrix.rotate(Eigen::AngleAxisd(rotation, Vec3d::UnitZ())); - matrix.scale(scaling_factor); - return bbox.transformed(matrix); + return bbox.transformed(world_matrix(dont_translate)); } void ModelInstance::transform_polygon(Polygon* polygon) const @@ -1046,4 +1024,20 @@ void ModelInstance::transform_polygon(Polygon* polygon) const polygon->scale(this->scaling_factor); // scale around polygon origin } +Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale) const +{ + Transform3d m = Transform3d::Identity(); + + if (!dont_translate) + m.translate(Vec3d(offset(0), offset(1), 0.0)); + + if (!dont_rotate) + m.rotate(Eigen::AngleAxisd(rotation, Vec3d::UnitZ())); + + if (!dont_scale) + m.scale(scaling_factor); + + return m; +} + } diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index f8a36527d..66b53618a 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -243,6 +243,8 @@ public: // To be called on an external polygon. It does not translate the polygon, only rotates and scales. void transform_polygon(Polygon* polygon) const; + Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const; + bool is_printable() const { return print_volume_state == PVS_Inside; } private: diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index 6840bc96e..6d40731f8 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -264,7 +264,7 @@ void TriangleMesh::rotate(float angle, const Vec3d& axis) Vec3f axis_norm = axis.cast().normalized(); Transform3f m = Transform3f::Identity(); m.rotate(Eigen::AngleAxisf(angle, axis_norm)); - stl_transform(&stl, (float*)m.data()); + stl_transform(&stl, m); } void TriangleMesh::mirror(const Axis &axis) @@ -279,6 +279,11 @@ void TriangleMesh::mirror(const Axis &axis) stl_invalidate_shared_vertices(&this->stl); } +void TriangleMesh::transform(const Transform3f& t) +{ + stl_transform(&stl, t); +} + void TriangleMesh::align_to_origin() { this->translate( @@ -523,9 +528,9 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d& t) const src_vertices(0, v_id) = (double)facet_ptr->vertex[i](0); src_vertices(1, v_id) = (double)facet_ptr->vertex[i](1); src_vertices(2, v_id) = (double)facet_ptr->vertex[i](2); + ++v_id; } facet_ptr += 1; - ++v_id; } } diff --git a/xs/src/libslic3r/TriangleMesh.hpp b/xs/src/libslic3r/TriangleMesh.hpp index 666252887..aebed4a2e 100644 --- a/xs/src/libslic3r/TriangleMesh.hpp +++ b/xs/src/libslic3r/TriangleMesh.hpp @@ -48,6 +48,7 @@ public: void mirror_x() { this->mirror(X); } void mirror_y() { this->mirror(Y); } void mirror_z() { this->mirror(Z); } + void transform(const Transform3f& t); void align_to_origin(); void rotate(double angle, Point* center); TriangleMeshPtrs split() const; diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 2980e34a1..a35165db4 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -1051,6 +1051,8 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const ::glPopMatrix(); } } + + ::glDisable(GL_BLEND); } void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const @@ -1278,9 +1280,7 @@ bool GLGizmoFlatten::is_plane_update_necessary() const } Vec3d GLGizmoFlatten::get_flattening_normal() const { - Transform3d m = Transform3d::Identity(); - m.rotate(Eigen::AngleAxisd(-m_model_object->instances.front()->rotation, Vec3d::UnitZ())); - Vec3d normal = m * m_normal; + Vec3d normal = m_model_object->instances.front()->world_matrix().matrix().block(0, 0, 3, 3) * m_normal; m_normal = Vec3d::Zero(); return normal; }