diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index a100f520a..0cfd3f115 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1,3 +1,4 @@ +#include "libslic3r.h" #include "Geometry.hpp" #include "ClipperUtils.hpp" #include "ExPolygon.hpp" @@ -369,12 +370,6 @@ contains(const std::vector &vector, const Point &point) } template bool contains(const ExPolygons &vector, const Point &point); -double -rad2deg(double angle) -{ - return angle / PI * 180.0; -} - double rad2deg_dir(double angle) { @@ -1232,4 +1227,161 @@ Vec3d extract_euler_angles(const Transform3d& transform) return extract_euler_angles(m); } +#if ENABLE_MODELVOLUME_TRANSFORM +Transformation::Flags::Flags() + : dont_translate(true) + , dont_rotate(true) + , dont_scale(true) +#if ENABLE_MIRROR + , dont_mirror(true) +#endif // ENABLE_MIRROR +{ +} + +#if ENABLE_MIRROR +bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const +{ + return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale) || (this->dont_mirror != dont_mirror); +} + +void Transformation::Flags::set(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) +{ + this->dont_translate = dont_translate; + this->dont_rotate = dont_rotate; + this->dont_scale = dont_scale; + this->dont_mirror = dont_mirror; +} +#else +bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale) const +{ + return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale); +} + +void Transformation::Flags::set(bool dont_translate, bool dont_rotate, bool dont_scale) +{ + this->dont_translate = dont_translate; + this->dont_rotate = dont_rotate; + this->dont_scale = dont_scale; +} +#endif // ENABLE_MIRROR + +Transformation::Transformation() + : m_offset(Vec3d::Zero()) + , m_rotation(Vec3d::Zero()) + , m_scaling_factor(Vec3d::Ones()) +#if ENABLE_MIRROR + , m_mirror(Vec3d::Ones()) +#endif // ENABLE_MIRROR + , m_matrix(Transform3d::Identity()) + , m_dirty(false) +{ +} + +void Transformation::set_offset(const Vec3d& offset) +{ + set_offset(X, offset(0)); + set_offset(Y, offset(1)); + set_offset(Z, offset(2)); +} + +void Transformation::set_offset(Axis axis, double offset) +{ + if (m_offset(axis) != offset) + { + m_offset(axis) = offset; + m_dirty = true; + } +} + +void Transformation::set_rotation(const Vec3d& rotation) +{ + set_rotation(X, rotation(0)); + set_rotation(Y, rotation(1)); + set_rotation(Z, rotation(2)); +} + +void Transformation::set_rotation(Axis axis, double rotation) +{ + rotation = angle_to_0_2PI(rotation); + + if (m_rotation(axis) = rotation) + { + m_rotation(axis) = rotation; + m_dirty = true; + } +} + +void Transformation::set_scaling_factor(const Vec3d& scaling_factor) +{ + set_scaling_factor(X, scaling_factor(0)); + set_scaling_factor(Y, scaling_factor(1)); + set_scaling_factor(Z, scaling_factor(2)); +} + +void Transformation::set_scaling_factor(Axis axis, double scaling_factor) +{ + if (m_scaling_factor(axis) != std::abs(scaling_factor)) + { + m_scaling_factor(axis) = std::abs(scaling_factor); + m_dirty = true; + } +} + +void Transformation::set_mirror(const Vec3d& mirror) +{ + set_mirror(X, mirror(0)); + set_mirror(Y, mirror(1)); + set_mirror(Z, mirror(2)); +} + +void Transformation::set_mirror(Axis axis, double mirror) +{ + double abs_mirror = std::abs(mirror); + if (abs_mirror == 0.0) + mirror = 1.0; + else if (abs_mirror != 1.0) + mirror /= abs_mirror; + + if (m_mirror(axis) != mirror) + { + m_mirror(axis) = mirror; + m_dirty = true; + } +} + +#if ENABLE_MIRROR +const Transform3d& Transformation::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const +#else +const Transform3d& Transformation::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale) const +#endif // ENABLE_MIRROR +{ +#if ENABLE_MIRROR + if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale, dont_mirror)) +#else + if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale)) +#endif // ENABLE_MIRROR + { + Vec3d translation = dont_translate ? Vec3d::Zero() : m_offset; + Vec3d rotation = dont_rotate ? Vec3d::Zero() : m_rotation; + Vec3d scale = dont_scale ? Vec3d::Ones() : m_scaling_factor; +#if ENABLE_MIRROR + Vec3d mirror = dont_mirror ? Vec3d::Ones() : m_mirror; + m_matrix = Geometry::assemble_transform(translation, rotation, scale, mirror); +#else + m_matrix = Geometry::assemble_transform(translation, rotation, scale); +#endif // ENABLE_MIRROR + +#if ENABLE_MIRROR + m_flags.set(dont_translate, dont_rotate, dont_scale, dont_mirror); +#else + m_flags.set(dont_translate, dont_rotate, dont_scale); +#endif // ENABLE_MIRROR + m_dirty = false; + } + + return m_matrix; +} + +#endif // ENABLE_MODELVOLUME_TRANSFORM + } } diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 9046add25..47fdec55a 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -117,9 +117,23 @@ void chained_path(const Points &points, std::vector &retval); template void chained_path_items(Points &points, T &items, T &retval); bool directions_parallel(double angle1, double angle2, double max_diff = 0); template bool contains(const std::vector &vector, const Point &point); -double rad2deg(double angle); +template T rad2deg(T angle) { return T(180.0) * angle / T(PI); } double rad2deg_dir(double angle); template T deg2rad(T angle) { return T(PI) * angle / T(180.0); } +template T angle_to_0_2PI(T angle) +{ + static const T TWO_PI = T(2) * T(PI); + while (angle < T(0)) + { + angle += TWO_PI; + } + while (TWO_PI < angle) + { + angle -= TWO_PI; + } + + return angle; +} void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval); double linint(double value, double oldmin, double oldmax, double newmin, double newmax); @@ -200,6 +214,79 @@ Vec3d extract_euler_angles(const Eigen::Matrix& // Returns the euler angles extracted from the given affine transform // Warning -> The transform should not contain any shear !!! Vec3d extract_euler_angles(const Transform3d& transform); + +#if ENABLE_MODELVOLUME_TRANSFORM +class Transformation +{ + struct Flags + { + bool dont_translate; + bool dont_rotate; + bool dont_scale; +#if ENABLE_MIRROR + bool dont_mirror; +#endif // ENABLE_MIRROR + + Flags(); + +#if ENABLE_MIRROR + bool needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const; + void set(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror); +#else + bool needs_update(bool dont_translate, bool dont_rotate, bool dont_scale) const; + void set(bool dont_translate, bool dont_rotate, bool dont_scale); +#endif // ENABLE_MIRROR + }; + + Vec3d m_offset; // In unscaled coordinates + Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point + Vec3d m_scaling_factor; // Scaling factors along the three axes +#if ENABLE_MIRROR + Vec3d m_mirror; // Mirroring along the three axes +#endif // ENABLE_MIRROR + mutable Transform3d m_matrix; + + mutable Flags m_flags; + mutable bool m_dirty; + +public: + Transformation(); + + const Vec3d& get_offset() const { return m_offset; } + double get_offset(Axis axis) const { return m_offset(axis); } + + void set_offset(const Vec3d& offset); + void set_offset(Axis axis, double offset); + + const Vec3d& get_rotation() const { return m_rotation; } + double get_rotation(Axis axis) const { return m_rotation(axis); } + + void set_rotation(const Vec3d& rotation); + void set_rotation(Axis axis, double rotation); + + Vec3d get_scaling_factor() const { return m_scaling_factor; } + double get_scaling_factor(Axis axis) const { return m_scaling_factor(axis); } + +#if ENABLE_MIRROR + void set_scaling_factor(const Vec3d& scaling_factor); + void set_scaling_factor(Axis axis, double scaling_factor); + + const Vec3d& get_mirror() const { return m_mirror; } + double get_mirror(Axis axis) const { return m_mirror(axis); } + + void set_mirror(const Vec3d& mirror); + void set_mirror(Axis axis, double mirror); + + const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const; +#else + void set_scaling_factor(const Vec3d& scaling_factor) { m_scaling_factor = scaling_factor; } + void set_scaling_factor(Axis axis, double scaling_factor) { m_scaling_factor(axis) = scaling_factor; } + + const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const; +#endif // ENABLE_MIRROR +}; +#endif // ENABLE_MODELVOLUME_TRANSFORM + } } #endif diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 15eedaa2d..b68d2a108 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1124,6 +1124,7 @@ size_t ModelVolume::split(unsigned int max_extruders) return idx; } +#if !ENABLE_MODELVOLUME_TRANSFORM void ModelInstance::set_rotation(const Vec3d& rotation) { set_rotation(X, rotation(0)); @@ -1176,6 +1177,7 @@ void ModelInstance::set_mirror(Axis axis, double mirror) m_mirror(axis) = mirror; } #endif // ENABLE_MIRROR +#endif // !ENABLE_MODELVOLUME_TRANSFORM void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const { @@ -1197,17 +1199,29 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes // Scale the bounding box along the three axes. for (unsigned int i = 0; i < 3; ++i) { +#if ENABLE_MODELVOLUME_TRANSFORM + if (std::abs(m_transformation.get_scaling_factor((Axis)i)-1.0) > EPSILON) + { + bbox.min(i) *= m_transformation.get_scaling_factor((Axis)i); + bbox.max(i) *= m_transformation.get_scaling_factor((Axis)i); +#else if (std::abs(this->m_scaling_factor(i) - 1.0) > EPSILON) { bbox.min(i) *= this->m_scaling_factor(i); bbox.max(i) *= this->m_scaling_factor(i); +#endif // ENABLE_MODELVOLUME_TRANSFORM } } // Translate the bounding box. if (! dont_translate) { +#if ENABLE_MODELVOLUME_TRANSFORM + bbox.min += m_transformation.get_offset(); + bbox.max += m_transformation.get_offset(); +#else bbox.min += this->m_offset; bbox.max += this->m_offset; +#endif // ENABLE_MODELVOLUME_TRANSFORM } } return bbox; @@ -1225,12 +1239,20 @@ Vec3d ModelInstance::transform_vector(const Vec3d& v, bool dont_translate) const void ModelInstance::transform_polygon(Polygon* polygon) const { +#if ENABLE_MODELVOLUME_TRANSFORM + // CHECK_ME -> Is the following correct or it should take in account all three rotations ? + polygon->rotate(m_transformation.get_rotation(Z)); // rotate around polygon origin + // CHECK_ME -> Is the following correct ? + polygon->scale(m_transformation.get_scaling_factor(X), m_transformation.get_scaling_factor(Y)); // scale around polygon origin +#else // CHECK_ME -> Is the following correct or it should take in account all three rotations ? polygon->rotate(this->m_rotation(2)); // rotate around polygon origin // CHECK_ME -> Is the following correct ? polygon->scale(this->m_scaling_factor(0), this->m_scaling_factor(1)); // scale around polygon origin +#endif // ENABLE_MODELVOLUME_TRANSFORM } +#if !ENABLE_MODELVOLUME_TRANSFORM #if ENABLE_MIRROR Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const #else @@ -1247,5 +1269,6 @@ Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, b return Geometry::assemble_transform(translation, rotation, scale); #endif // ENABLE_MIRROR } +#endif // !ENABLE_MODELVOLUME_TRANSFORM } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 89b068c40..9739956a8 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -11,6 +11,9 @@ #include #include #include +#if ENABLE_MODELVOLUME_TRANSFORM +#include "Geometry.hpp" +#endif // ENABLE_MODELVOLUME_TRANSFORM namespace Slic3r { @@ -210,6 +213,10 @@ class ModelVolume : public ModelBase // The convex hull of this model's mesh. TriangleMesh m_convex_hull; +#if ENABLE_MODELVOLUME_TRANSFORM + Geometry::Transformation m_transformation; +#endif // ENABLE_MODELVOLUME_TRANSFORM + public: std::string name; // The triangular model. @@ -257,6 +264,34 @@ public: static Type type_from_string(const std::string &s); static std::string type_to_string(const Type t); +#if ENABLE_MODELVOLUME_TRANSFORM + const Vec3d& get_offset() const { return m_transformation.get_offset(); } + double get_offset(Axis axis) const { return m_transformation.get_offset(axis); } + + void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); } + void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); } + + const Vec3d& get_rotation() const { return m_transformation.get_rotation(); } + double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); } + + void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); } + void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); } + + Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); } + double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); } + + void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); } + void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); } + +#if ENABLE_MIRROR + const Vec3d& get_mirror() const { return m_transformation.get_mirror(); } + double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); } + + void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); } + void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); } +#endif // ENABLE_MIRROR +#endif // ENABLE_MODELVOLUME_TRANSFORM + private: // Parent object owning this ModelVolume. ModelObject* object; @@ -306,12 +341,16 @@ public: friend class ModelObject; private: +#if ENABLE_MODELVOLUME_TRANSFORM + Geometry::Transformation m_transformation; +#else Vec3d m_offset; // in unscaled coordinates Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point Vec3d m_scaling_factor; // Scaling factors along the three axes #if ENABLE_MIRROR Vec3d m_mirror; // Mirroring along the three axes #endif // ENABLE_MIRROR +#endif // ENABLE_MODELVOLUME_TRANSFORM public: // flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state()) @@ -319,6 +358,36 @@ public: ModelObject* get_object() const { return this->object; } +#if ENABLE_MODELVOLUME_TRANSFORM + const Geometry::Transformation& get_transformation() const { return m_transformation; } + void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; } + + const Vec3d& get_offset() const { return m_transformation.get_offset(); } + double get_offset(Axis axis) const { return m_transformation.get_offset(axis); } + + void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); } + void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); } + + const Vec3d& get_rotation() const { return m_transformation.get_rotation(); } + double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); } + + void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); } + void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); } + + Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); } + double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); } + + void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); } + void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); } + +#if ENABLE_MIRROR + const Vec3d& get_mirror() const { return m_transformation.get_mirror(); } + double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); } + + void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); } + void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); } +#endif // ENABLE_MIRROR +#else const Vec3d& get_offset() const { return m_offset; } double get_offset(Axis axis) const { return m_offset(axis); } @@ -349,6 +418,7 @@ public: void set_mirror(const Vec3d& mirror); void set_mirror(Axis axis, double mirror); #endif // ENABLE_MIRROR +#endif // ENABLE_MODELVOLUME_TRANSFORM // To be called on an external mesh void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const; @@ -361,11 +431,19 @@ public: // To be called on an external polygon. It does not translate the polygon, only rotates and scales. void transform_polygon(Polygon* polygon) const; +#if ENABLE_MODELVOLUME_TRANSFORM +#if ENABLE_MIRROR + const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.world_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); } +#else + const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const { return m_transformation.world_matrix(dont_translate, dont_rotate, dont_scale); } +#endif // ENABLE_MIRROR +#else #if ENABLE_MIRROR Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const; #else Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const; #endif // ENABLE_MIRROR +#endif // ENABLE_MODELVOLUME_TRANSFORM bool is_printable() const { return print_volume_state == PVS_Inside; } @@ -373,6 +451,11 @@ private: // Parent object, owning this instance. ModelObject* object; +#if ENABLE_MODELVOLUME_TRANSFORM + ModelInstance(ModelObject *object) : object(object), print_volume_state(PVS_Inside) {} + ModelInstance(ModelObject *object, const ModelInstance &other) : + m_transformation(other.m_transformation), object(object), print_volume_state(PVS_Inside) {} +#else #if ENABLE_MIRROR ModelInstance(ModelObject *object) : m_offset(Vec3d::Zero()), m_rotation(Vec3d::Zero()), m_scaling_factor(Vec3d::Ones()), m_mirror(Vec3d::Ones()), object(object), print_volume_state(PVS_Inside) {} ModelInstance(ModelObject *object, const ModelInstance &other) : @@ -382,6 +465,7 @@ private: ModelInstance(ModelObject *object, const ModelInstance &other) : m_rotation(other.m_rotation), m_scaling_factor(other.m_scaling_factor), m_offset(other.m_offset), object(object), print_volume_state(PVS_Inside) {} #endif // ENABLE_MIRROR +#endif // ENABLE_MODELVOLUME_TRANSFORM explicit ModelInstance(ModelInstance &rhs) = delete; ModelInstance& operator=(ModelInstance &rhs) = delete; diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index a01c95f72..fe3b19eb0 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -24,6 +24,8 @@ #define ENABLE_MIRROR (1 && ENABLE_1_42_0) // Modified camera target behavior #define ENABLE_MODIFIED_CAMERA_TARGET (1 && ENABLE_1_42_0) +// Add Geometry::Transformation class and use it into ModelInstance, ModelVolume and GLVolume +#define ENABLE_MODELVOLUME_TRANSFORM (1 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 91f60947c..a85a27e1d 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -195,6 +195,9 @@ const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f }; const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f }; GLVolume::GLVolume(float r, float g, float b, float a) +#if ENABLE_MODELVOLUME_TRANSFORM + : m_transformed_bounding_box_dirty(true) +#else : m_offset(Vec3d::Zero()) , m_rotation(Vec3d::Zero()) , m_scaling_factor(Vec3d::Ones()) @@ -204,6 +207,7 @@ GLVolume::GLVolume(float r, float g, float b, float a) , m_world_matrix(Transform3f::Identity()) , m_world_matrix_dirty(true) , m_transformed_bounding_box_dirty(true) +#endif // ENABLE_MODELVOLUME_TRANSFORM , m_transformed_convex_hull_bounding_box_dirty(true) , m_convex_hull(nullptr) , composite_id(-1) @@ -260,6 +264,7 @@ void GLVolume::set_render_color() set_render_color(color, 4); } +#if !ENABLE_MODELVOLUME_TRANSFORM const Vec3d& GLVolume::get_rotation() const { return m_rotation; @@ -360,6 +365,7 @@ void GLVolume::set_mirror(Axis axis, double mirror) } } #endif // ENABLE_MIRROR +#endif // !ENABLE_MODELVOLUME_TRANSFORM void GLVolume::set_convex_hull(const TriangleMesh& convex_hull) { @@ -386,6 +392,7 @@ void GLVolume::set_drag_group_id(const std::string& drag_by) } #endif // !ENABLE_EXTENDED_SELECTION +#if !ENABLE_MODELVOLUME_TRANSFORM const Transform3f& GLVolume::world_matrix() const { if (m_world_matrix_dirty) @@ -399,12 +406,17 @@ const Transform3f& GLVolume::world_matrix() const } return m_world_matrix; } +#endif // !ENABLE_MODELVOLUME_TRANSFORM const BoundingBoxf3& GLVolume::transformed_bounding_box() const { if (m_transformed_bounding_box_dirty) { +#if ENABLE_MODELVOLUME_TRANSFORM + m_transformed_bounding_box = bounding_box.transformed(world_matrix()); +#else m_transformed_bounding_box = bounding_box.transformed(world_matrix().cast()); +#endif // ENABLE_MODELVOLUME_TRANSFORM m_transformed_bounding_box_dirty = false; } @@ -415,10 +427,17 @@ const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const { if (m_transformed_convex_hull_bounding_box_dirty) { +#if ENABLE_MODELVOLUME_TRANSFORM + if ((m_convex_hull != nullptr) && (m_convex_hull->stl.stats.number_of_facets > 0)) + m_transformed_convex_hull_bounding_box = m_convex_hull->transformed_bounding_box(world_matrix()); + else + m_transformed_convex_hull_bounding_box = bounding_box.transformed(world_matrix()); +#else if ((m_convex_hull != nullptr) && (m_convex_hull->stl.stats.number_of_facets > 0)) m_transformed_convex_hull_bounding_box = m_convex_hull->transformed_bounding_box(world_matrix().cast()); else m_transformed_convex_hull_bounding_box = bounding_box.transformed(world_matrix().cast()); +#endif // ENABLE_MODELVOLUME_TRANSFORM m_transformed_convex_hull_bounding_box_dirty = false; } @@ -469,7 +488,11 @@ void GLVolume::render() const ::glCullFace(GL_BACK); ::glPushMatrix(); +#if ENABLE_MODELVOLUME_TRANSFORM + ::glMultMatrixd(world_matrix().data()); +#else ::glMultMatrixf(world_matrix().data()); +#endif // ENABLE_MODELVOLUME_TRANSFORM if (this->indexed_vertex_array.indexed()) this->indexed_vertex_array.render(this->tverts_range, this->qverts_range); else @@ -507,7 +530,11 @@ void GLVolume::render_using_layer_height() const glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width); if (world_matrix_id >= 0) +#if ENABLE_MODELVOLUME_TRANSFORM + ::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data()); +#else ::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data()); +#endif // ENABLE_MODELVOLUME_TRANSFORM GLsizei w = (GLsizei)layer_height_texture_width(); GLsizei h = (GLsizei)layer_height_texture_height(); @@ -567,7 +594,11 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); if (worldmatrix_id != -1) +#if ENABLE_MODELVOLUME_TRANSFORM + ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data()); +#else ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data()); +#endif // ENABLE_MODELVOLUME_TRANSFORM render(); @@ -586,7 +617,11 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); if (worldmatrix_id != -1) +#if ENABLE_MODELVOLUME_TRANSFORM + ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast().data()); +#else ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data()); +#endif // ENABLE_MODELVOLUME_TRANSFORM ::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id); ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); @@ -594,7 +629,11 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c ::glPushMatrix(); +#if ENABLE_MODELVOLUME_TRANSFORM + ::glMultMatrixd(world_matrix().data()); +#else ::glMultMatrixf(world_matrix().data()); +#endif // ENABLE_MODELVOLUME_TRANSFORM if (n_triangles > 0) { @@ -638,7 +677,11 @@ void GLVolume::render_legacy() const ::glPushMatrix(); +#if ENABLE_MODELVOLUME_TRANSFORM + ::glMultMatrixd(world_matrix().data()); +#else ::glMultMatrixf(world_matrix().data()); +#endif // ENABLE_MODELVOLUME_TRANSFORM if (n_triangles > 0) ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first); @@ -767,12 +810,16 @@ std::vector GLVolumeCollection::load_object( } v.is_modifier = ! model_volume->is_model_part(); v.shader_outside_printer_detection_enabled = model_volume->is_model_part(); +#if ENABLE_MODELVOLUME_TRANSFORM + v.set_transformation(instance->get_transformation()); +#else v.set_offset(instance->get_offset()); v.set_rotation(instance->get_rotation()); v.set_scaling_factor(instance->get_scaling_factor()); #if ENABLE_MIRROR v.set_mirror(instance->get_mirror()); #endif // ENABLE_MIRROR +#endif // ENABLE_MODELVOLUME_TRANSFORM } } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 7e74ff92f..8c2427915 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -254,6 +254,9 @@ public: GLVolume(const float *rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {} private: +#if ENABLE_MODELVOLUME_TRANSFORM + Geometry::Transformation m_transformation; +#else // Offset of the volume to be rendered. Vec3d m_offset; // Rotation around three axes of the volume to be rendered. @@ -268,6 +271,7 @@ private: mutable Transform3f m_world_matrix; // Whether or not is needed to recalculate the world matrix. mutable bool m_world_matrix_dirty; +#endif // ENABLE_MODELVOLUME_TRANSFORM // Bounding box of this volume, in unscaled coordinates. mutable BoundingBoxf3 m_transformed_bounding_box; // Whether or not is needed to recalculate the transformed bounding box. @@ -280,7 +284,6 @@ private: mutable bool m_transformed_convex_hull_bounding_box_dirty; public: - // Bounding box of this volume, in unscaled coordinates. BoundingBoxf3 bounding_box; // Color of the triangles / quads held by this volume. @@ -333,6 +336,36 @@ public: // Sets render color in dependence of current state void set_render_color(); +#if ENABLE_MODELVOLUME_TRANSFORM + const Geometry::Transformation& get_transformation() const { return m_transformation; } + void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; set_bounding_boxes_as_dirty(); } + + const Vec3d& get_offset() const { return m_transformation.get_offset(); } + double get_offset(Axis axis) const { return m_transformation.get_offset(axis); } + + void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); set_bounding_boxes_as_dirty(); } + void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); set_bounding_boxes_as_dirty(); } + + const Vec3d& get_rotation() const { return m_transformation.get_rotation(); } + double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); } + + void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); } + void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); } + + Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); } + double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); } + + void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); } + void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); set_bounding_boxes_as_dirty(); } + +#if ENABLE_MIRROR + const Vec3d& get_mirror() const { return m_transformation.get_mirror(); } + double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); } + + void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); set_bounding_boxes_as_dirty(); } + void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); set_bounding_boxes_as_dirty(); } +#endif // ENABLE_MIRROR +#else const Vec3d& get_rotation() const; void set_rotation(const Vec3d& rotation); @@ -350,6 +383,7 @@ public: const Vec3d& get_offset() const; void set_offset(const Vec3d& offset); +#endif // ENABLE_MODELVOLUME_TRANSFORM void set_convex_hull(const TriangleMesh& convex_hull); @@ -362,7 +396,11 @@ public: int volume_idx() const { return (this->composite_id / 1000) % 1000; } int instance_idx() const { return this->composite_id % 1000; } +#if ENABLE_MODELVOLUME_TRANSFORM + const Transform3d& world_matrix() const { return m_transformation.world_matrix(); } +#else const Transform3f& world_matrix() const; +#endif // ENABLE_MODELVOLUME_TRANSFORM const BoundingBoxf3& transformed_bounding_box() const; const BoundingBoxf3& transformed_convex_hull_bounding_box() const; @@ -412,6 +450,10 @@ public: } void reset_layer_height_texture_data() { layer_height_texture_data.reset(); } + +#if ENABLE_MODELVOLUME_TRANSFORM + void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; } +#endif // ENABLE_MODELVOLUME_TRANSFORM }; #if ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 6965d95b7..62fba6c5a 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -926,7 +926,11 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // gets transform from first selected volume const GLVolume* v = selection.get_volume(*idxs.begin()); +#if ENABLE_MODELVOLUME_TRANSFORM + transform = v->world_matrix(); +#else transform = v->world_matrix().cast(); +#endif // ENABLE_MODELVOLUME_TRANSFORM // gets angles from first selected volume angles = v->get_rotation();