Tech ENABLE_TRANSFORMATIONS_BY_MATRICES - Reworked method void Selection::scale(const Vec3d& scale, TransformationType transformation_type) to use matrix multiplication

This commit is contained in:
enricoturri1966 2022-05-11 10:54:42 +02:00
parent d64d89ac52
commit c9520eda62
13 changed files with 704 additions and 391 deletions

View File

@ -313,7 +313,6 @@ Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation,
return transform; return transform;
} }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void assemble_transform(Transform3d& transform, const Transform3d& translation, const Transform3d& rotation, const Transform3d& scale, const Transform3d& mirror) void assemble_transform(Transform3d& transform, const Transform3d& translation, const Transform3d& rotation, const Transform3d& scale, const Transform3d& mirror)
{ {
transform = translation * rotation * scale * mirror; transform = translation * rotation * scale * mirror;
@ -326,6 +325,19 @@ Transform3d assemble_transform(const Transform3d& translation, const Transform3d
return transform; return transform;
} }
void translation_transform(Transform3d& transform, const Vec3d& translation)
{
transform = Transform3d::Identity();
transform.translate(translation);
}
Transform3d translation_transform(const Vec3d& translation)
{
Transform3d transform;
translation_transform(transform, translation);
return transform;
}
void rotation_transform(Transform3d& transform, const Vec3d& rotation) void rotation_transform(Transform3d& transform, const Vec3d& rotation)
{ {
transform = Transform3d::Identity(); transform = Transform3d::Identity();
@ -351,7 +363,6 @@ Transform3d scale_transform(const Vec3d& scale)
scale_transform(transform, scale); scale_transform(transform, scale);
return transform; return transform;
} }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix) Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix)
{ {
@ -433,6 +444,14 @@ static std::pair<Transform3d, Transform3d> extract_rotation_scale(const Transfor
return { Transform3d(rotation), Transform3d(scale) }; return { Transform3d(rotation), Transform3d(scale) };
} }
static bool contains_skew(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return !scale.isDiagonal();
}
Vec3d Transformation::get_rotation() const Vec3d Transformation::get_rotation() const
{ {
return extract_euler_angles(extract_rotation(m_matrix)); return extract_euler_angles(extract_rotation(m_matrix));
@ -623,6 +642,12 @@ void Transformation::set_mirror(Axis axis, double mirror)
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES #endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
} }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
bool Transformation::has_skew() const
{
return contains_skew(m_matrix);
}
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES #if !ENABLE_TRANSFORMATIONS_BY_MATRICES
void Transformation::set_from_transform(const Transform3d& transform) void Transformation::set_from_transform(const Transform3d& transform)
{ {

View File

@ -336,7 +336,6 @@ void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d
Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(),
const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones()); const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
// Sets the given transform by multiplying the given transformations in the following order: // Sets the given transform by multiplying the given transformations in the following order:
// T = translation * rotation * scale * mirror // T = translation * rotation * scale * mirror
void assemble_transform(Transform3d& transform, const Transform3d& translation = Transform3d::Identity(), void assemble_transform(Transform3d& transform, const Transform3d& translation = Transform3d::Identity(),
@ -348,6 +347,12 @@ void assemble_transform(Transform3d& transform, const Transform3d& translation =
Transform3d assemble_transform(const Transform3d& translation = Transform3d::Identity(), const Transform3d& rotation = Transform3d::Identity(), Transform3d assemble_transform(const Transform3d& translation = Transform3d::Identity(), const Transform3d& rotation = Transform3d::Identity(),
const Transform3d& scale = Transform3d::Identity(), const Transform3d& mirror = Transform3d::Identity()); const Transform3d& scale = Transform3d::Identity(), const Transform3d& mirror = Transform3d::Identity());
// Sets the given transform by assembling the given translation
void translation_transform(Transform3d& transform, const Vec3d& translation);
// Returns the transform obtained by assembling the given translation
Transform3d translation_transform(const Vec3d& translation);
// Sets the given transform by assembling the given rotations in the following order: // Sets the given transform by assembling the given rotations in the following order:
// 1) rotate X // 1) rotate X
// 2) rotate Y // 2) rotate Y
@ -365,7 +370,6 @@ void scale_transform(Transform3d& transform, const Vec3d& scale);
// Returns the transform obtained by assembling the given scale factors // Returns the transform obtained by assembling the given scale factors
Transform3d scale_transform(const Vec3d& scale); Transform3d scale_transform(const Vec3d& scale);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
// Returns the euler angles extracted from the given rotation matrix // Returns the euler angles extracted from the given rotation matrix
// Warning -> The matrix should not contain any scale or shear !!! // Warning -> The matrix should not contain any scale or shear !!!
@ -478,6 +482,10 @@ public:
void set_mirror(const Vec3d& mirror); void set_mirror(const Vec3d& mirror);
void set_mirror(Axis axis, double mirror); void set_mirror(Axis axis, double mirror);
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
bool has_skew() const;
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES #if !ENABLE_TRANSFORMATIONS_BY_MATRICES
void set_from_transform(const Transform3d& transform); void set_from_transform(const Transform3d& transform);
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES #endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES

View File

@ -2914,7 +2914,13 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
else else
displacement = multiplier * direction; displacement = multiplier * direction;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
TransformationType trafo_type;
trafo_type.set_relative();
m_selection.translate(displacement, trafo_type);
#else
m_selection.translate(displacement); m_selection.translate(displacement);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
m_dirty = true; m_dirty = true;
} }
); );
@ -3579,7 +3585,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
} }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
TransformationType trafo_type;
trafo_type.set_relative();
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D, trafo_type);
#else
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D); m_selection.translate(cur_pos - m_mouse.drag.start_position_3D);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects)
update_sequential_clearance(); update_sequential_clearance();
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
@ -3996,12 +4008,12 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
Selection::EMode selection_mode = m_selection.get_mode(); Selection::EMode selection_mode = m_selection.get_mode();
for (const GLVolume* v : m_volumes.volumes) { for (const GLVolume* v : m_volumes.volumes) {
int object_idx = v->object_idx(); const int object_idx = v->object_idx();
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx) if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
continue; continue;
int instance_idx = v->instance_idx(); const int instance_idx = v->instance_idx();
int volume_idx = v->volume_idx(); const int volume_idx = v->volume_idx();
done.insert(std::pair<int, int>(object_idx, instance_idx)); done.insert(std::pair<int, int>(object_idx, instance_idx));
@ -4009,13 +4021,22 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
ModelObject* model_object = m_model->objects[object_idx]; ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) { if (model_object != nullptr) {
if (selection_mode == Selection::Instance) { if (selection_mode == Selection::Instance) {
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
#else
model_object->instances[instance_idx]->set_scaling_factor(v->get_instance_scaling_factor()); model_object->instances[instance_idx]->set_scaling_factor(v->get_instance_scaling_factor());
model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
} }
else if (selection_mode == Selection::Volume) { else if (selection_mode == Selection::Volume) {
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
#else
model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor()); model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor());
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset()); model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
} }
model_object->invalidate_bounding_box(); model_object->invalidate_bounding_box();
} }
@ -4024,10 +4045,10 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
// Fixes sinking/flying instances // Fixes sinking/flying instances
for (const std::pair<int, int>& i : done) { for (const std::pair<int, int>& i : done) {
ModelObject* m = m_model->objects[i.first]; ModelObject* m = m_model->objects[i.first];
double shift_z = m->get_instance_min_z(i.second); const double shift_z = m->get_instance_min_z(i.second);
// leave sinking instances as sinking // leave sinking instances as sinking
if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) { if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) {
Vec3d shift(0.0, 0.0, -shift_z); const Vec3d shift(0.0, 0.0, -shift_z);
m_selection.translate(i.first, i.second, shift); m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift); m->translate_instance(i.second, shift);
} }

View File

@ -461,9 +461,16 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
m_reset_scale_button->SetToolTip(_L("Reset scale")); m_reset_scale_button->SetToolTip(_L("Reset scale"));
m_reset_scale_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { m_reset_scale_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset scale")); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset scale"));
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
bool old_uniform = m_uniform_scale;
m_uniform_scale = true;
change_scale_value(0, 100.0);
m_uniform_scale = old_uniform;
#else
change_scale_value(0, 100.); change_scale_value(0, 100.);
change_scale_value(1, 100.); change_scale_value(1, 100.);
change_scale_value(2, 100.); change_scale_value(2, 100.);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}); });
editors_grid_sizer->Add(m_reset_scale_button); editors_grid_sizer->Add(m_reset_scale_button);
@ -616,6 +623,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_position = volume->get_instance_offset(); m_new_position = volume->get_instance_offset();
#endif // !ENABLE_WORLD_COORDINATE #endif // !ENABLE_WORLD_COORDINATE
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible. // Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
if (is_world_coordinates() && !m_uniform_scale && if (is_world_coordinates() && !m_uniform_scale &&
@ -627,6 +635,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_uniform_scale = true; m_uniform_scale = true;
m_lock_bnt->SetLock(true); m_lock_bnt->SetLock(true);
} }
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
if (is_world_coordinates()) { if (is_world_coordinates()) {
@ -790,6 +799,7 @@ void ObjectManipulation::update_if_dirty()
update(m_cache.rotation, m_cache.rotation_rounded, meRotation, m_new_rotation); update(m_cache.rotation, m_cache.rotation_rounded, meRotation, m_new_rotation);
} }
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
Selection::EUniformScaleRequiredReason reason; Selection::EUniformScaleRequiredReason reason;
if (selection.requires_uniform_scale(&reason)) { if (selection.requires_uniform_scale(&reason)) {
@ -829,10 +839,13 @@ void ObjectManipulation::update_if_dirty()
#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED #endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
} }
else { else {
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
m_lock_bnt->SetLock(m_uniform_scale); m_lock_bnt->SetLock(m_uniform_scale);
m_lock_bnt->SetToolTip(wxEmptyString); m_lock_bnt->SetToolTip(wxEmptyString);
m_lock_bnt->enable(); m_lock_bnt->enable();
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
} }
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
#if !ENABLE_WORLD_COORDINATE #if !ENABLE_WORLD_COORDINATE
{ {
@ -1048,7 +1061,19 @@ void ObjectManipulation::change_position_value(int axis, double value)
Selection& selection = canvas->get_selection(); Selection& selection = canvas->get_selection();
selection.setup_cache(); selection.setup_cache();
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
TransformationType trafo_type;
trafo_type.set_relative();
switch (get_coordinates_type())
{
case ECoordinatesType::Instance: { trafo_type.set_instance(); break; }
case ECoordinatesType::Local: { trafo_type.set_local(); break; }
default: { break; }
}
selection.translate(position - m_cache.position, trafo_type);
#else
selection.translate(position - m_cache.position, get_coordinates_type()); selection.translate(position - m_cache.position, get_coordinates_type());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#else #else
selection.translate(position - m_cache.position, selection.requires_local_axes()); selection.translate(position - m_cache.position, selection.requires_local_axes());
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
@ -1191,6 +1216,9 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
transformation_type.set_local(); transformation_type.set_local();
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED #endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
#else
bool uniform_scale = m_uniform_scale || selection.requires_uniform_scale(); bool uniform_scale = m_uniform_scale || selection.requires_uniform_scale();
Vec3d scaling_factor = uniform_scale ? scale(axis) * Vec3d::Ones() : scale; Vec3d scaling_factor = uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
@ -1203,6 +1231,7 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
scaling_factor = (mv * mi * scaling_factor).cwiseAbs(); scaling_factor = (mv * mi * scaling_factor).cwiseAbs();
} }
} }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#else #else
TransformationType transformation_type(TransformationType::World_Relative_Joint); TransformationType transformation_type(TransformationType::World_Relative_Joint);
if (selection.is_single_full_instance()) { if (selection.is_single_full_instance()) {
@ -1231,6 +1260,12 @@ void ObjectManipulation::do_size(int axis, const Vec3d& scale) const
else if (is_instance_coordinates()) else if (is_instance_coordinates())
transformation_type.set_instance(); transformation_type.set_instance();
if (!is_local_coordinates())
transformation_type.set_relative();
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
#else
bool uniform_scale = m_uniform_scale || selection.requires_uniform_scale(); bool uniform_scale = m_uniform_scale || selection.requires_uniform_scale();
Vec3d scaling_factor = uniform_scale ? scale(axis) * Vec3d::Ones() : scale; Vec3d scaling_factor = uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
@ -1243,6 +1278,7 @@ void ObjectManipulation::do_size(int axis, const Vec3d& scale) const
scaling_factor = (mv * mi * scaling_factor).cwiseAbs(); scaling_factor = (mv * mi * scaling_factor).cwiseAbs();
} }
} }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
selection.setup_cache(); selection.setup_cache();
selection.scale(scaling_factor, transformation_type); selection.scale(scaling_factor, transformation_type);
@ -1303,6 +1339,10 @@ void ObjectManipulation::set_uniform_scaling(const bool use_uniform_scale)
} }
m_uniform_scale = use_uniform_scale; m_uniform_scale = use_uniform_scale;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
set_dirty();
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#else #else
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
if (selection.is_single_full_instance() && is_world_coordinates() && !use_uniform_scale) { if (selection.is_single_full_instance() && is_world_coordinates() && !use_uniform_scale) {

View File

@ -1,23 +1,23 @@
#include "GLGizmoBase.hpp" #include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <GL/glew.h>
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#if ENABLE_GL_SHADERS_ATTRIBUTES #if ENABLE_GL_SHADERS_ATTRIBUTES
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
// TODO: Display tooltips quicker on Linux // TODO: Display tooltips quicker on Linux
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
const float GLGizmoBase::Grabber::SizeFactor = 0.05f; const float GLGizmoBase::Grabber::SizeFactor = 0.05f;
const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::MinHalfSize = 1.5f;
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
GLModel GLGizmoBase::Grabber::s_cube; GLModel GLGizmoBase::Grabber::s_cube;
GLModel GLGizmoBase::Grabber::s_cone; GLModel GLGizmoBase::Grabber::s_cone;
@ -30,35 +30,35 @@ GLGizmoBase::Grabber::~Grabber()
if (s_cone.is_initialized()) if (s_cone.is_initialized())
s_cone.reset(); s_cone.reset();
} }
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
float GLGizmoBase::Grabber::get_half_size(float size) const float GLGizmoBase::Grabber::get_half_size(float size) const
{ {
return std::max(size * SizeFactor, MinHalfSize); return std::max(size * SizeFactor, MinHalfSize);
} }
float GLGizmoBase::Grabber::get_dragging_half_size(float size) const float GLGizmoBase::Grabber::get_dragging_half_size(float size) const
{ {
return get_half_size(size) * DraggingScaleFactor; return get_half_size(size) * DraggingScaleFactor;
} }
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking)
{ {
#if ENABLE_GL_SHADERS_ATTRIBUTES #if ENABLE_GL_SHADERS_ATTRIBUTES
GLShaderProgram* shader = wxGetApp().get_current_shader(); GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader == nullptr) if (shader == nullptr)
return; return;
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
if (!s_cube.is_initialized()) { if (!s_cube.is_initialized()) {
#else #else
if (!m_cube.is_initialized()) { if (!m_cube.is_initialized()) {
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
// This cannot be done in constructor, OpenGL is not yet // This cannot be done in constructor, OpenGL is not yet
// initialized at that point (on Linux at least). // initialized at that point (on Linux at least).
indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0); indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0);
its_translate(its, -0.5f * Vec3f::Ones()); its_translate(its, -0.5f * Vec3f::Ones());
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
s_cube.init_from(its); s_cube.init_from(its);
@ -71,9 +71,9 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
#else #else
m_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); m_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
} }
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
if (!s_cone.is_initialized()) if (!s_cone.is_initialized())
s_cone.init_from(its_make_cone(0.375, 1.5, double(PI) / 18.0)); s_cone.init_from(its_make_cone(0.375, 1.5, double(PI) / 18.0));
@ -83,8 +83,8 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
const float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size); const float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size);
#else #else
const float fullsize = 2.0f * (dragging ? get_dragging_half_size(size) : get_half_size(size)); const float fullsize = 2.0f * (dragging ? get_dragging_half_size(size) : get_half_size(size));
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
s_cube.set_color(render_color); s_cube.set_color(render_color);
@ -99,32 +99,32 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
#else #else
m_cube.set_color(-1, render_color); m_cube.set_color(-1, render_color);
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES #if ENABLE_GL_SHADERS_ATTRIBUTES
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones()); const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones());
#else #else
const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, fullsize * Vec3d::Ones()); const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, fullsize * Vec3d::Ones());
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
const Transform3d& projection_matrix = camera.get_projection_matrix(); const Transform3d& projection_matrix = camera.get_projection_matrix();
shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", projection_matrix); shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
#else #else
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
glsafe(::glTranslated(center.x(), center.y(), center.z())); glsafe(::glTranslated(center.x(), center.y(), center.z()));
glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0)); glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0));
glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0)); glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
glsafe(::glScaled(2.0 * half_size, 2.0 * half_size, 2.0 * half_size)); glsafe(::glScaled(2.0 * half_size, 2.0 * half_size, 2.0 * half_size));
#else #else
glsafe(::glScaled(fullsize, fullsize, fullsize)); glsafe(::glScaled(fullsize, fullsize, fullsize));
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if ENABLE_GIZMO_GRABBER_REFACTOR #if ENABLE_GIZMO_GRABBER_REFACTOR
s_cube.render(); s_cube.render();
@ -198,234 +198,234 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else #else
m_cube.render(); m_cube.render();
#endif // ENABLE_GIZMO_GRABBER_REFACTOR #endif // ENABLE_GIZMO_GRABBER_REFACTOR
#if !ENABLE_GL_SHADERS_ATTRIBUTES #if !ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES #endif // !ENABLE_GL_SHADERS_ATTRIBUTES
} }
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: m_parent(parent) : m_parent(parent)
, m_group_id(-1) , m_group_id(-1)
, m_state(Off) , m_state(Off)
, m_shortcut_key(0) , m_shortcut_key(0)
, m_icon_filename(icon_filename) , m_icon_filename(icon_filename)
, m_sprite_id(sprite_id) , m_sprite_id(sprite_id)
, m_hover_id(-1) , m_hover_id(-1)
, m_dragging(false) , m_dragging(false)
, m_imgui(wxGetApp().imgui()) , m_imgui(wxGetApp().imgui())
, m_first_input_window_render(true) , m_first_input_window_render(true)
, m_dirty(false) , m_dirty(false)
{ {
} }
void GLGizmoBase::set_hover_id(int id) void GLGizmoBase::set_hover_id(int id)
{ {
// do not change hover id during dragging // do not change hover id during dragging
assert(!m_dragging); assert(!m_dragging);
// allow empty grabbers when not using grabbers but use hover_id - flatten, rotate // allow empty grabbers when not using grabbers but use hover_id - flatten, rotate
if (!m_grabbers.empty() && id >= (int) m_grabbers.size()) if (!m_grabbers.empty() && id >= (int) m_grabbers.size())
return; return;
m_hover_id = id; m_hover_id = id;
on_set_hover_id(); on_set_hover_id();
} }
bool GLGizmoBase::update_items_state() bool GLGizmoBase::update_items_state()
{ {
bool res = m_dirty; bool res = m_dirty;
m_dirty = false; m_dirty = false;
return res; return res;
} }
ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const
{ {
id = BASE_ID - id; id = BASE_ID - id;
if (m_group_id > -1) if (m_group_id > -1)
id -= m_group_id; id -= m_group_id;
return picking_decode(id); return picking_decode(id);
} }
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
{ {
render_grabbers((float)((box.size().x() + box.size().y() + box.size().z()) / 3.0)); render_grabbers((float)((box.size().x() + box.size().y() + box.size().z()) / 3.0));
} }
void GLGizmoBase::render_grabbers(float size) const void GLGizmoBase::render_grabbers(float size) const
{ {
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr) if (shader == nullptr)
return; return;
shader->start_using(); shader->start_using();
shader->set_uniform("emission_factor", 0.1f); shader->set_uniform("emission_factor", 0.1f);
for (int i = 0; i < (int)m_grabbers.size(); ++i) { for (int i = 0; i < (int)m_grabbers.size(); ++i) {
if (m_grabbers[i].enabled) if (m_grabbers[i].enabled)
m_grabbers[i].render(m_hover_id == i, size); m_grabbers[i].render(m_hover_id == i, size);
} }
shader->stop_using(); shader->stop_using();
} }
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
{ {
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
GLShaderProgram* shader = wxGetApp().get_shader("flat"); GLShaderProgram* shader = wxGetApp().get_shader("flat");
if (shader != nullptr) { if (shader != nullptr) {
shader->start_using(); shader->start_using();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0);
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) {
if (m_grabbers[i].enabled) { if (m_grabbers[i].enabled) {
m_grabbers[i].color = picking_color_component(i); m_grabbers[i].color = picking_color_component(i);
m_grabbers[i].render_for_picking(mean_size); m_grabbers[i].render_for_picking(mean_size);
} }
} }
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
shader->stop_using(); shader->stop_using();
} }
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
} }
// help function to process grabbers // help function to process grabbers
// call start_dragging, stop_dragging, on_dragging // call start_dragging, stop_dragging, on_dragging
bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) { bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
bool is_dragging_finished = false; bool is_dragging_finished = false;
if (mouse_event.Moving()) { if (mouse_event.Moving()) {
// it should not happen but for sure // it should not happen but for sure
assert(!m_dragging); assert(!m_dragging);
if (m_dragging) is_dragging_finished = true; if (m_dragging) is_dragging_finished = true;
else return false; else return false;
} }
if (mouse_event.LeftDown()) { if (mouse_event.LeftDown()) {
Selection &selection = m_parent.get_selection(); Selection &selection = m_parent.get_selection();
if (!selection.is_empty() && m_hover_id != -1 && if (!selection.is_empty() && m_hover_id != -1 &&
(m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))) { (m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))) {
selection.setup_cache(); selection.setup_cache();
m_dragging = true; m_dragging = true;
for (auto &grabber : m_grabbers) grabber.dragging = false; for (auto &grabber : m_grabbers) grabber.dragging = false;
if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size())) if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size()))
m_grabbers[m_hover_id].dragging = true; m_grabbers[m_hover_id].dragging = true;
// prevent change of hover_id during dragging // prevent change of hover_id during dragging
m_parent.set_mouse_as_dragging(); m_parent.set_mouse_as_dragging();
on_start_dragging(); on_start_dragging();
// Let the plater know that the dragging started // Let the plater know that the dragging started
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED)); m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED));
m_parent.set_as_dirty(); m_parent.set_as_dirty();
return true; return true;
} }
} else if (m_dragging) { } else if (m_dragging) {
// when mouse cursor leave window than finish actual dragging operation // when mouse cursor leave window than finish actual dragging operation
bool is_leaving = mouse_event.Leaving(); bool is_leaving = mouse_event.Leaving();
if (mouse_event.Dragging()) { if (mouse_event.Dragging()) {
m_parent.set_mouse_as_dragging(); m_parent.set_mouse_as_dragging();
Point mouse_coord(mouse_event.GetX(), mouse_event.GetY()); Point mouse_coord(mouse_event.GetX(), mouse_event.GetY());
auto ray = m_parent.mouse_ray(mouse_coord); auto ray = m_parent.mouse_ray(mouse_coord);
UpdateData data(ray, mouse_coord); UpdateData data(ray, mouse_coord);
on_dragging(data); on_dragging(data);
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
m_parent.set_as_dirty(); m_parent.set_as_dirty();
return true; return true;
} }
else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) { else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) {
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED #if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
do_stop_dragging(is_leaving); do_stop_dragging(is_leaving);
#else #else
for (auto &grabber : m_grabbers) grabber.dragging = false; for (auto &grabber : m_grabbers) grabber.dragging = false;
m_dragging = false; m_dragging = false;
// NOTE: This should be part of GLCanvas3D // NOTE: This should be part of GLCanvas3D
// Reset hover_id when leave window // Reset hover_id when leave window
if (is_leaving) m_parent.mouse_up_cleanup(); if (is_leaving) m_parent.mouse_up_cleanup();
on_stop_dragging(); on_stop_dragging();
// There is prediction that after draggign, data are changed // There is prediction that after draggign, data are changed
// Data are updated twice also by canvas3D::reload_scene. // Data are updated twice also by canvas3D::reload_scene.
// Should be fixed. // Should be fixed.
m_parent.get_gizmos_manager().update_data(); m_parent.get_gizmos_manager().update_data();
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
// Let the plater know that the dragging finished, so a delayed // Let the plater know that the dragging finished, so a delayed
// refresh of the scene with the background processing data should // refresh of the scene with the background processing data should
// be performed. // be performed.
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
// updates camera target constraints // updates camera target constraints
m_parent.refresh_camera_scene_box(); m_parent.refresh_camera_scene_box();
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED #endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
return true; return true;
} }
} }
return false; return false;
} }
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED #if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
void GLGizmoBase::do_stop_dragging(bool perform_mouse_cleanup) void GLGizmoBase::do_stop_dragging(bool perform_mouse_cleanup)
{ {
for (auto& grabber : m_grabbers) grabber.dragging = false; for (auto& grabber : m_grabbers) grabber.dragging = false;
m_dragging = false; m_dragging = false;
// NOTE: This should be part of GLCanvas3D // NOTE: This should be part of GLCanvas3D
// Reset hover_id when leave window // Reset hover_id when leave window
if (perform_mouse_cleanup) m_parent.mouse_up_cleanup(); if (perform_mouse_cleanup) m_parent.mouse_up_cleanup();
on_stop_dragging(); on_stop_dragging();
// There is prediction that after draggign, data are changed // There is prediction that after draggign, data are changed
// Data are updated twice also by canvas3D::reload_scene. // Data are updated twice also by canvas3D::reload_scene.
// Should be fixed. // Should be fixed.
m_parent.get_gizmos_manager().update_data(); m_parent.get_gizmos_manager().update_data();
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
// Let the plater know that the dragging finished, so a delayed // Let the plater know that the dragging finished, so a delayed
// refresh of the scene with the background processing data should // refresh of the scene with the background processing data should
// be performed. // be performed.
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
// updates camera target constraints // updates camera target constraints
m_parent.refresh_camera_scene_box(); m_parent.refresh_camera_scene_box();
} }
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED #endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
std::string GLGizmoBase::format(float value, unsigned int decimals) const std::string GLGizmoBase::format(float value, unsigned int decimals) const
{ {
return Slic3r::string_printf("%.*f", decimals, value); return Slic3r::string_printf("%.*f", decimals, value);
} }
void GLGizmoBase::set_dirty() { void GLGizmoBase::set_dirty() {
m_dirty = true; m_dirty = true;
} }
void GLGizmoBase::render_input_window(float x, float y, float bottom_limit) void GLGizmoBase::render_input_window(float x, float y, float bottom_limit)
{ {
on_render_input_window(x, y, bottom_limit); on_render_input_window(x, y, bottom_limit);
if (m_first_input_window_render) { if (m_first_input_window_render) {
// for some reason, the imgui dialogs are not shown on screen in the 1st frame where they are rendered, but show up only with the 2nd rendered frame // for some reason, the imgui dialogs are not shown on screen in the 1st frame where they are rendered, but show up only with the 2nd rendered frame
// so, we forces another frame rendering the first time the imgui window is shown // so, we forces another frame rendering the first time the imgui window is shown
m_parent.set_as_dirty(); m_parent.set_as_dirty();
m_first_input_window_render = false; m_first_input_window_render = false;
} }
} }
std::string GLGizmoBase::get_name(bool include_shortcut) const std::string GLGizmoBase::get_name(bool include_shortcut) const
{ {
int key = get_shortcut_key(); int key = get_shortcut_key();
std::string out = on_get_name(); std::string out = on_get_name();
if (include_shortcut && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z) if (include_shortcut && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z)
out += std::string(" [") + char(int('A') + key - int(WXK_CONTROL_A)) + "]"; out += std::string(" [") + char(int('A') + key - int(WXK_CONTROL_A)) + "]";
return out; return out;
} }
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -126,7 +126,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
#else #else
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse();
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES #endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * trafo.get_matrix(); const Transform3d instance_matrix = Geometry::translation_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * trafo.get_matrix();
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d& view_matrix = camera.get_view_matrix(); const Transform3d& view_matrix = camera.get_view_matrix();

View File

@ -141,7 +141,19 @@ void GLGizmoMove3D::on_dragging(const UpdateData& data)
Selection &selection = m_parent.get_selection(); Selection &selection = m_parent.get_selection();
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
TransformationType trafo_type;
trafo_type.set_relative();
switch (wxGetApp().obj_manipul()->get_coordinates_type())
{
case ECoordinatesType::Instance: { trafo_type.set_instance(); break; }
case ECoordinatesType::Local: { trafo_type.set_local(); break; }
default: { break; }
}
selection.translate(m_displacement, trafo_type);
#else
selection.translate(m_displacement, wxGetApp().obj_manipul()->get_coordinates_type()); selection.translate(m_displacement, wxGetApp().obj_manipul()->get_coordinates_type());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#else #else
selection.translate(m_displacement); selection.translate(m_displacement);
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE

View File

@ -787,7 +787,7 @@ Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
} }
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
return Geometry::assemble_transform(m_center) * m_orient_matrix * ret; return Geometry::translation_transform(m_center) * m_orient_matrix * ret;
#else #else
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
ret = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true) * ret; ret = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true) * ret;

View File

@ -41,6 +41,9 @@ GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filen
std::string GLGizmoScale3D::get_tooltip() const std::string GLGizmoScale3D::get_tooltip() const
{ {
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
const Vec3d scale = 100.0 * m_scale;
#else
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
Vec3d scale = 100.0 * Vec3d::Ones(); Vec3d scale = 100.0 * Vec3d::Ones();
@ -52,6 +55,7 @@ std::string GLGizmoScale3D::get_tooltip() const
else if (selection.is_single_modifier() || selection.is_single_volume()) else if (selection.is_single_modifier() || selection.is_single_volume())
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
scale = 100.0 * selection.get_first_volume()->get_volume_scaling_factor(); scale = 100.0 * selection.get_first_volume()->get_volume_scaling_factor();
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
if (m_hover_id == 0 || m_hover_id == 1 || m_grabbers[0].dragging || m_grabbers[1].dragging) if (m_hover_id == 0 || m_hover_id == 1 || m_grabbers[0].dragging || m_grabbers[1].dragging)
return "X: " + format(scale.x(), 4) + "%"; return "X: " + format(scale.x(), 4) + "%";
@ -91,33 +95,48 @@ bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
// Apply new temporary scale factors // Apply new temporary scale factors
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
TransformationType transformation_type; TransformationType transformation_type;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
if (wxGetApp().obj_manipul()->is_local_coordinates())
transformation_type.set_local();
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
transformation_type.set_instance();
transformation_type.set_relative();
#else
if (!wxGetApp().obj_manipul()->is_world_coordinates()) if (!wxGetApp().obj_manipul()->is_world_coordinates())
transformation_type.set_local(); transformation_type.set_local();
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#else #else
TransformationType transformation_type(TransformationType::Local_Absolute_Joint); TransformationType transformation_type(TransformationType::Local_Absolute_Joint);
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
if (mouse_event.AltDown()) transformation_type.set_independent(); if (mouse_event.AltDown()) transformation_type.set_independent();
Selection &selection = m_parent.get_selection(); #if ENABLE_TRANSFORMATIONS_BY_MATRICES
m_parent.get_selection().scale_and_translate(m_scale, m_offset, transformation_type);
#else
Selection& selection = m_parent.get_selection();
selection.scale(m_scale, transformation_type); selection.scale(m_scale, transformation_type);
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
if (mouse_event.CmdDown()) selection.translate(m_offset, wxGetApp().obj_manipul()->get_coordinates_type()); if (mouse_event.CmdDown()) selection.translate(m_offset, wxGetApp().obj_manipul()->get_coordinates_type());
#else #else
if (mouse_event.CmdDown()) selection.translate(m_offset, true); if (mouse_event.CmdDown()) selection.translate(m_offset, true);
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES #if !ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED #if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
} }
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED #endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES #endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
} }
} }
return use_grabbers(mouse_event); return use_grabbers(mouse_event);
} }
void GLGizmoScale3D::data_changed() void GLGizmoScale3D::data_changed()
{ {
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
const Selection &selection = m_parent.get_selection(); const Selection &selection = m_parent.get_selection();
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED #if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
bool enable_scale_xyz = !selection.requires_uniform_scale(); bool enable_scale_xyz = !selection.requires_uniform_scale();
@ -127,6 +146,9 @@ void GLGizmoScale3D::data_changed()
selection.is_single_volume() || selection.is_single_volume() ||
selection.is_single_modifier(); selection.is_single_modifier();
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
set_scale(Vec3d::Ones());
#else
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED #if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) { if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
#else #else
@ -151,6 +173,7 @@ void GLGizmoScale3D::data_changed()
} }
else else
set_scale(Vec3d::Ones()); set_scale(Vec3d::Ones());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
} }
bool GLGizmoScale3D::on_init() bool GLGizmoScale3D::on_init()
@ -268,7 +291,7 @@ void GLGizmoScale3D::on_render()
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
const Transform3d inst_trafo = v.get_instance_transformation().get_matrix_no_scaling_factor(); const Transform3d inst_trafo = v.get_instance_transformation().get_matrix_no_scaling_factor();
m_grabbers_transform = inst_trafo * Geometry::assemble_transform(m_bounding_box.center()); m_grabbers_transform = inst_trafo * Geometry::translation_transform(m_bounding_box.center());
m_center = inst_trafo * m_bounding_box.center(); m_center = inst_trafo * m_bounding_box.center();
#else #else
m_grabbers_transform = v.get_instance_transformation().get_matrix(false, false, true) * Geometry::assemble_transform(m_bounding_box.center()); m_grabbers_transform = v.get_instance_transformation().get_matrix(false, false, true) * Geometry::assemble_transform(m_bounding_box.center());
@ -698,6 +721,58 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
} }
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
{
double ratio = calc_ratio(data);
if (ratio > 0.0) {
Vec3d curr_scale = m_scale;
Vec3d starting_scale = m_starting.scale;
const Selection& selection = m_parent.get_selection();
const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
curr_scale(axis) = starting_scale(axis) * ratio;
m_scale = curr_scale;
if (m_starting.ctrl_down && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier())) {
double local_offset = 0.5 * (ratio - 1.0) * m_starting.box.size()(axis);
if (m_hover_id == 2 * axis)
local_offset *= -1.0;
Vec3d center_offset = m_starting.instance_center - m_starting.center; // world coordinates (== Vec3d::Zero() for single volume selection)
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
// from world coordinates to instance coordinates
center_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix().inverse() * center_offset;
local_offset += (ratio - 1.0) * center_offset(axis);
switch (axis)
{
case X: { m_offset = local_offset * Vec3d::UnitX(); break; }
case Y: { m_offset = local_offset * Vec3d::UnitY(); break; }
case Z: { m_offset = local_offset * Vec3d::UnitZ(); break; }
default: { m_offset = Vec3d::Zero(); break; }
}
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
// from instance coordinates to world coordinates
m_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix() * m_offset;
if (selection.is_single_volume_or_modifier()) {
if (coordinates_type == ECoordinatesType::Instance)
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() * m_offset;
else if (coordinates_type == ECoordinatesType::Local) {
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() *
selection.get_first_volume()->get_volume_transformation().get_rotation_matrix() * m_offset;
}
}
}
else
m_offset = Vec3d::Zero();
}
}
#else
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data) void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
{ {
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
@ -742,6 +817,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
if (ratio > 0.0) { if (ratio > 0.0) {
m_scale(axis) = m_starting.scale(axis) * ratio; m_scale(axis) = m_starting.scale(axis) * ratio;
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
if (m_starting.ctrl_down) { if (m_starting.ctrl_down) {
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
double local_offset = 0.5 * (ratio - 1.0) * m_starting.box.size()(axis); double local_offset = 0.5 * (ratio - 1.0) * m_starting.box.size()(axis);
@ -755,7 +831,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
Vec3d center_offset = m_starting.instance_center - m_starting.center; Vec3d center_offset = m_starting.instance_center - m_starting.center;
if (selection.is_single_full_instance() && coordinates_type != ECoordinatesType::World) { if (selection.is_single_full_instance() && coordinates_type != ECoordinatesType::World) {
const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), selection.get_first_volume()->get_instance_rotation()).inverse(); const Transform3d m = Geometry::rotation_transform(selection.get_first_volume()->get_instance_rotation()).inverse();
center_offset = m * center_offset; center_offset = m * center_offset;
} }
@ -785,12 +861,57 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
m_offset = Vec3d::Zero(); m_offset = Vec3d::Zero();
} }
} }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void GLGizmoScale3D::do_scale_uniform(const UpdateData & data)
{
const double ratio = calc_ratio(data);
if (ratio > 0.0) {
m_scale = m_starting.scale * ratio;
const Selection& selection = m_parent.get_selection();
const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
if (m_starting.ctrl_down && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier())) {
m_offset = 0.5 * (ratio - 1.0) * m_starting.box.size();
if (m_hover_id == 6 || m_hover_id == 9)
m_offset.x() *= -1.0;
if (m_hover_id == 6 || m_hover_id == 7)
m_offset.y() *= -1.0;
Vec3d center_offset = m_starting.instance_center - m_starting.center; // world coordinates (== Vec3d::Zero() for single volume selection)
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
// from world coordinates to instance coordinates
center_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix().inverse() * center_offset;
m_offset += (ratio - 1.0) * center_offset;
if (selection.is_single_full_instance() && coordinates_type == ECoordinatesType::Local)
// from instance coordinates to world coordinates
m_offset = selection.get_first_volume()->get_instance_transformation().get_rotation_matrix() * m_offset;
if (selection.is_single_volume_or_modifier()) {
if (coordinates_type == ECoordinatesType::Instance)
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() * m_offset;
else if (coordinates_type == ECoordinatesType::Local) {
m_offset = selection.get_first_volume()->get_instance_transformation().get_scaling_factor_matrix().inverse() *
selection.get_first_volume()->get_volume_transformation().get_rotation_matrix() * m_offset;
}
}
}
else
m_offset = Vec3d::Zero();
}
}
#else
void GLGizmoScale3D::do_scale_uniform(const UpdateData& data) void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
{ {
const double ratio = calc_ratio(data); const double ratio = calc_ratio(data);
if (ratio > 0.0) { if (ratio > 0.0) {
m_scale = m_starting.scale * ratio; m_scale = m_starting.scale * ratio;
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
if (m_starting.ctrl_down) { if (m_starting.ctrl_down) {
m_offset = 0.5 * (ratio - 1.0) * m_starting.box.size(); m_offset = 0.5 * (ratio - 1.0) * m_starting.box.size();
@ -804,7 +925,7 @@ void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
Vec3d center_offset = m_starting.instance_center - m_starting.center; Vec3d center_offset = m_starting.instance_center - m_starting.center;
if (selection.is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) { if (selection.is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) {
const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), selection.get_first_volume()->get_instance_rotation()).inverse(); const Transform3d m = Geometry::rotation_transform(selection.get_first_volume()->get_instance_rotation()).inverse();
center_offset = m * center_offset; center_offset = m * center_offset;
} }
@ -815,6 +936,7 @@ void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
m_offset = Vec3d::Zero(); m_offset = Vec3d::Zero();
} }
} }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
{ {

View File

@ -69,7 +69,11 @@ public:
void set_snap_step(double step) { m_snap_step = step; } void set_snap_step(double step) { m_snap_step = step; }
const Vec3d& get_scale() const { return m_scale; } const Vec3d& get_scale() const { return m_scale; }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; m_offset = Vec3d::Zero(); }
#else
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; } void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
std::string get_tooltip() const override; std::string get_tooltip() const override;

View File

@ -3849,7 +3849,7 @@ void Plater::priv::reload_from_disk()
new_volume->set_type(old_volume->type()); new_volume->set_type(old_volume->type());
new_volume->set_material_id(old_volume->material_id()); new_volume->set_material_id(old_volume->material_id());
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
new_volume->set_transformation(Geometry::assemble_transform(old_volume->source.transform.get_offset()) * new_volume->set_transformation(Geometry::translation_transform(old_volume->source.transform.get_offset()) *
old_volume->get_transformation().get_matrix_no_offset() * old_volume->source.transform.get_matrix_no_offset()); old_volume->get_transformation().get_matrix_no_offset() * old_volume->source.transform.get_matrix_no_offset());
new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * (new_volume->source.mesh_offset - old_volume->source.mesh_offset)); new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
#else #else

View File

@ -598,6 +598,7 @@ bool Selection::matches(const std::vector<unsigned int>& volume_idxs) const
return count == (unsigned int)m_list.size(); return count == (unsigned int)m_list.size();
} }
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
bool Selection::requires_uniform_scale(EUniformScaleRequiredReason* reason) const bool Selection::requires_uniform_scale(EUniformScaleRequiredReason* reason) const
#else #else
@ -666,6 +667,7 @@ bool Selection::requires_uniform_scale() const
return true; return true;
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
} }
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
int Selection::get_object_idx() const int Selection::get_object_idx() const
{ {
@ -759,58 +761,29 @@ void Selection::setup_cache()
} }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
void Selection::translate(const Vec3d& displacement, ECoordinatesType type) void Selection::translate(const Vec3d& displacement, TransformationType transformation_type)
{ {
if (!m_valid) if (!m_valid)
return; return;
assert(transformation_type.relative());
for (unsigned int i : m_list) { for (unsigned int i : m_list) {
GLVolume& v = *(*m_volumes)[i]; GLVolume& v = *(*m_volumes)[i];
const VolumeCache& volume_data = m_cache.volumes_data[i]; const VolumeCache& volume_data = m_cache.volumes_data[i];
if (m_mode == Instance && !is_wipe_tower()) { if (m_mode == Instance && !is_wipe_tower()) {
assert(is_from_fully_selected_instance(i)); assert(is_from_fully_selected_instance(i));
switch (type) if (transformation_type.world())
{ v.set_instance_transformation(Geometry::translation_transform(displacement) * volume_data.get_instance_full_matrix());
case ECoordinatesType::World: else if (transformation_type.local()) {
{ const Vec3d world_displacement = volume_data.get_instance_rotation_matrix() * displacement;
v.set_instance_transformation(Geometry::assemble_transform(displacement) * volume_data.get_instance_full_matrix()); v.set_instance_transformation(Geometry::translation_transform(world_displacement) * volume_data.get_instance_full_matrix());
break;
}
case ECoordinatesType::Local:
{
const Vec3d world_displacemet = volume_data.get_instance_rotation_matrix() * displacement;
v.set_instance_transformation(Geometry::assemble_transform(world_displacemet) * volume_data.get_instance_full_matrix());
break;
}
default: { assert(false); break; }
}
}
else {
switch (type)
{
case ECoordinatesType::World:
{
const Transform3d inst_matrix_no_offset = volume_data.get_instance_rotation_matrix() * volume_data.get_instance_scale_matrix();
const Vec3d inst_displacement = inst_matrix_no_offset.inverse() * displacement;
v.set_volume_transformation(Geometry::assemble_transform(inst_displacement) * volume_data.get_volume_full_matrix());
break;
}
case ECoordinatesType::Instance:
{
const Vec3d inst_displacement = volume_data.get_instance_scale_matrix().inverse() * displacement;
v.set_volume_transformation(Geometry::assemble_transform(inst_displacement) * volume_data.get_volume_full_matrix());
break;
}
case ECoordinatesType::Local:
{
const Vec3d inst_displacement = volume_data.get_instance_scale_matrix().inverse() *
volume_data.get_volume_rotation_matrix() * displacement;
v.set_volume_transformation(Geometry::assemble_transform(inst_displacement) * volume_data.get_volume_full_matrix());
break;
}
default: { assert(false); break; }
} }
else
assert(false);
} }
else
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement));
} }
#if !DISABLE_INSTANCES_SYNCH #if !DISABLE_INSTANCES_SYNCH
@ -913,51 +886,35 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
for (unsigned int i : m_list) { for (unsigned int i : m_list) {
GLVolume& v = *(*m_volumes)[i]; GLVolume& v = *(*m_volumes)[i];
const VolumeCache& volume_data = m_cache.volumes_data[i]; const VolumeCache& volume_data = m_cache.volumes_data[i];
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
if (m_mode == Instance && !is_wipe_tower()) { if (m_mode == Instance && !is_wipe_tower()) {
assert(is_from_fully_selected_instance(i)); assert(is_from_fully_selected_instance(i));
const Geometry::Transformation& old_trafo = volume_data.get_instance_transform();
Transform3d new_rotation_matrix = Transform3d::Identity(); Transform3d new_rotation_matrix = Transform3d::Identity();
if (transformation_type.absolute()) if (transformation_type.absolute())
new_rotation_matrix = rotation_matrix; new_rotation_matrix = rotation_matrix;
else { else {
if (transformation_type.world()) if (transformation_type.world())
new_rotation_matrix = rotation_matrix * old_trafo.get_rotation_matrix(); new_rotation_matrix = rotation_matrix * inst_trafo.get_rotation_matrix();
else if (transformation_type.local()) else if (transformation_type.local())
new_rotation_matrix = old_trafo.get_rotation_matrix() * rotation_matrix; new_rotation_matrix = inst_trafo.get_rotation_matrix() * rotation_matrix;
else else
assert(false); assert(false);
} }
const Vec3d new_offset = transformation_type.independent() ? old_trafo.get_offset() : const Vec3d new_offset = transformation_type.independent() ? inst_trafo.get_offset() :
m_cache.dragging_center + new_rotation_matrix * old_trafo.get_rotation_matrix().inverse() * m_cache.dragging_center + new_rotation_matrix * inst_trafo.get_rotation_matrix().inverse() *
(old_trafo.get_offset() - m_cache.dragging_center); (inst_trafo.get_offset() - m_cache.dragging_center);
v.set_instance_transformation(Geometry::assemble_transform(Geometry::assemble_transform(new_offset), new_rotation_matrix, v.set_instance_transformation(Geometry::assemble_transform(Geometry::translation_transform(new_offset), new_rotation_matrix,
old_trafo.get_scaling_factor_matrix(), old_trafo.get_mirror_matrix())); inst_trafo.get_scaling_factor_matrix(), inst_trafo.get_mirror_matrix()));
} }
else { else {
const Geometry::Transformation& old_trafo = volume_data.get_volume_transform(); if (transformation_type.absolute()) {
Transform3d new_rotation_matrix = Transform3d::Identity(); const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
v.set_volume_transformation(Geometry::assemble_transform(volume_trafo.get_offset_matrix(), Geometry::rotation_transform(rotation),
if (transformation_type.absolute()) volume_trafo.get_scaling_factor_matrix(), volume_trafo.get_mirror_matrix()));
new_rotation_matrix = rotation_matrix;
else {
if (transformation_type.world()) {
const Transform3d inst_rotation_matrix = volume_data.get_instance_transform().get_rotation_matrix();
new_rotation_matrix = inst_rotation_matrix.inverse() * rotation_matrix * inst_rotation_matrix * old_trafo.get_rotation_matrix();
}
else if (transformation_type.instance())
new_rotation_matrix = rotation_matrix * old_trafo.get_rotation_matrix();
else if (transformation_type.local())
new_rotation_matrix = old_trafo.get_rotation_matrix() * rotation_matrix;
else
assert(false);
} }
else
const Vec3d new_offset = !is_wipe_tower() ? old_trafo.get_offset() : transform_volume_relative(v, volume_data, transformation_type, Geometry::rotation_transform(rotation));
m_cache.dragging_center + new_rotation_matrix * old_trafo.get_rotation_matrix().inverse() *
(old_trafo.get_offset() - m_cache.dragging_center);
v.set_volume_transformation(Geometry::assemble_transform(Geometry::assemble_transform(new_offset), new_rotation_matrix,
old_trafo.get_scaling_factor_matrix(), old_trafo.get_mirror_matrix()));
} }
} }
@ -1181,6 +1138,12 @@ void Selection::flattening_rotate(const Vec3d& normal)
this->set_bounding_boxes_dirty(); this->set_bounding_boxes_dirty();
} }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void Selection::scale(const Vec3d& scale, TransformationType transformation_type)
{
scale_and_translate(scale, Vec3d::Zero(), transformation_type);
}
#else
void Selection::scale(const Vec3d& scale, TransformationType transformation_type) void Selection::scale(const Vec3d& scale, TransformationType transformation_type)
{ {
if (!m_valid) if (!m_valid)
@ -1255,6 +1218,7 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
set_bounding_boxes_dirty(); set_bounding_boxes_dirty();
wxGetApp().plater()->canvas3D()->requires_check_outside_state(); wxGetApp().plater()->canvas3D()->requires_check_outside_state();
} }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void Selection::scale_to_fit_print_volume(const BuildVolume& volume) void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
{ {
@ -1277,7 +1241,13 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
// center selection on print bed // center selection on print bed
setup_cache(); setup_cache();
offset.z() = -get_bounding_box().min.z(); offset.z() = -get_bounding_box().min.z();
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
TransformationType trafo_type;
trafo_type.set_relative();
translate(offset, trafo_type);
#else
translate(offset); translate(offset);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
@ -1367,7 +1337,78 @@ void Selection::mirror(Axis axis)
set_bounding_boxes_dirty(); set_bounding_boxes_dirty();
} }
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation, TransformationType transformation_type)
{
if (!m_valid)
return;
std::cout << "Selection::scale_and_translate: " << to_string(scale) << " - " << to_string(translation) << "\n";
for (unsigned int i : m_list) {
GLVolume& v = *(*m_volumes)[i];
const VolumeCache& volume_data = m_cache.volumes_data[i];
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
if (m_mode == Instance) {
assert(is_from_fully_selected_instance(i));
if (transformation_type.absolute()) {
assert(transformation_type.local());
assert(transformation_type.joint());
v.set_instance_transformation(Geometry::assemble_transform(inst_trafo.get_offset_matrix(), inst_trafo.get_rotation_matrix(),
Geometry::scale_transform(scale), inst_trafo.get_mirror_matrix()));
}
else {
if (transformation_type.world()) {
const Transform3d scale_matrix = Geometry::scale_transform(scale);
const Transform3d offset_matrix = (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) ?
// non-constrained scaling - add offset to scale around selection center
Geometry::translation_transform(m_cache.dragging_center + scale_matrix * (inst_trafo.get_offset() - m_cache.dragging_center)) :
// constrained scaling - add offset to keep constraint
Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix();
v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset());
}
else if (transformation_type.local()) {
const Transform3d scale_matrix = Geometry::scale_transform(scale);
Vec3d offset;
if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) {
// non-constrained scaling - add offset to scale around selection center
offset = inst_trafo.get_matrix_no_offset().inverse() * (inst_trafo.get_offset() - m_cache.dragging_center);
offset = inst_trafo.get_matrix_no_offset() * (scale_matrix * offset - offset);
}
else
// constrained scaling - add offset to keep constraint
offset = translation;
v.set_instance_transformation(Geometry::translation_transform(offset) * inst_trafo.get_matrix() * scale_matrix);
}
else
assert(false);
}
}
else {
if (transformation_type.absolute()) {
assert(transformation_type.local());
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
v.set_volume_transformation(Geometry::assemble_transform(volume_trafo.get_offset_matrix(), volume_trafo.get_rotation_matrix(),
Geometry::scale_transform(scale), volume_trafo.get_mirror_matrix()));
}
else
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale));
}
}
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
synchronize_unselected_instances(SyncRotationType::NONE);
else if (m_mode == Volume)
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
ensure_on_bed();
set_bounding_boxes_dirty();
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
#else
void Selection::translate(unsigned int object_idx, const Vec3d& displacement) void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
{ {
if (!m_valid) if (!m_valid)
@ -1416,7 +1457,7 @@ void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
this->set_bounding_boxes_dirty(); this->set_bounding_boxes_dirty();
} }
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES #endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void Selection::translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement) void Selection::translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement)
{ {
@ -1427,7 +1468,7 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
GLVolume& v = *(*m_volumes)[i]; GLVolume& v = *(*m_volumes)[i];
if (v.object_idx() == (int)object_idx && v.instance_idx() == (int)instance_idx) if (v.object_idx() == (int)object_idx && v.instance_idx() == (int)instance_idx)
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
v.set_instance_transformation(Geometry::assemble_transform(displacement) * v.get_instance_transformation().get_matrix()); v.set_instance_transformation(Geometry::translation_transform(displacement) * v.get_instance_transformation().get_matrix());
#else #else
v.set_instance_offset(v.get_instance_offset() + displacement); v.set_instance_offset(v.get_instance_offset() + displacement);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES #endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
@ -1464,7 +1505,7 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
continue; continue;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
v.set_instance_transformation(Geometry::assemble_transform(displacement) * v.get_instance_transformation().get_matrix()); v.set_instance_transformation(Geometry::translation_transform(displacement) * v.get_instance_transformation().get_matrix());
#else #else
v.set_instance_offset(v.get_instance_offset() + displacement); v.set_instance_offset(v.get_instance_offset() + displacement);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES #endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
@ -2764,7 +2805,11 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field, GLS
void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) void Selection::render_sidebar_scale_hints(const std::string& sidebar_field)
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
{ {
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
const bool uniform_scale = wxGetApp().obj_manipul()->get_uniform_scaling();
#else
const bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling(); const bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_GL_SHADERS_ATTRIBUTES #if ENABLE_GL_SHADERS_ATTRIBUTES
auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis, GLShaderProgram& shader, const Transform3d& matrix) { auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis, GLShaderProgram& shader, const Transform3d& matrix) {
@ -3375,5 +3420,27 @@ void Selection::paste_objects_from_clipboard()
#endif /* _DEBUG */ #endif /* _DEBUG */
} }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void Selection::transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
const Transform3d& transform)
{
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
if (transformation_type.world()) {
const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
const Transform3d new_volume_matrix = inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset;
volume.set_volume_transformation(volume_trafo.get_offset_matrix() * new_volume_matrix * volume_trafo.get_matrix_no_offset());
}
else if (transformation_type.instance())
volume.set_volume_transformation(volume_trafo.get_offset_matrix() * transform * volume_trafo.get_matrix_no_offset());
else if (transformation_type.local()) {
const Geometry::Transformation trafo(transform);
volume.set_volume_transformation(trafo.get_offset_matrix() * volume_trafo.get_matrix() * trafo.get_matrix_no_offset());
}
else
assert(false);
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -336,7 +336,9 @@ public:
VolumeNotAxisAligned_Instance, VolumeNotAxisAligned_Instance,
MultipleSelection, MultipleSelection,
}; };
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
bool requires_uniform_scale(EUniformScaleRequiredReason* reason = nullptr) const; bool requires_uniform_scale(EUniformScaleRequiredReason* reason = nullptr) const;
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
#else #else
bool requires_uniform_scale() const; bool requires_uniform_scale() const;
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
@ -365,7 +367,11 @@ public:
void setup_cache(); void setup_cache();
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void translate(const Vec3d& displacement, TransformationType transformation_type);
#else
void translate(const Vec3d& displacement, ECoordinatesType type = ECoordinatesType::World); void translate(const Vec3d& displacement, ECoordinatesType type = ECoordinatesType::World);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#else #else
void translate(const Vec3d& displacement, bool local = false); void translate(const Vec3d& displacement, bool local = false);
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
@ -374,6 +380,9 @@ public:
void scale(const Vec3d& scale, TransformationType transformation_type); void scale(const Vec3d& scale, TransformationType transformation_type);
void scale_to_fit_print_volume(const BuildVolume& volume); void scale_to_fit_print_volume(const BuildVolume& volume);
void mirror(Axis axis); void mirror(Axis axis);
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void scale_and_translate(const Vec3d& scale, const Vec3d& translation, TransformationType transformation_type);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES #if !ENABLE_TRANSFORMATIONS_BY_MATRICES
void translate(unsigned int object_idx, const Vec3d& displacement); void translate(unsigned int object_idx, const Vec3d& displacement);
@ -468,6 +477,11 @@ private:
void paste_volumes_from_clipboard(); void paste_volumes_from_clipboard();
void paste_objects_from_clipboard(); void paste_objects_from_clipboard();
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
const Transform3d& transform);
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}; };
} // namespace GUI } // namespace GUI