Tech ENABLE_WORLD_COORDINATE - Gizmo rotate oriented in dependence of the selected coordinate system
Fixed conflicts during rebase with master
This commit is contained in:
parent
61e7eb4ade
commit
ca5742c401
9 changed files with 155 additions and 54 deletions
|
@ -619,7 +619,7 @@ Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot
|
|||
double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
{
|
||||
const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||
const Vec3d axis = angle_axis.axis();
|
||||
const Vec3d& axis = angle_axis.axis();
|
||||
const double angle = angle_axis.angle();
|
||||
#ifndef NDEBUG
|
||||
if (std::abs(angle) > 1e-8) {
|
||||
|
|
|
@ -278,7 +278,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
return;
|
||||
|
||||
// Update mirroring at the GLVolumes.
|
||||
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
|
||||
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
|
||||
selection.synchronize_unselected_volumes();
|
||||
// Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
||||
canvas->do_mirror(L("Set Mirror"));
|
||||
|
@ -379,7 +379,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
return;
|
||||
|
||||
// Update rotation at the GLVolumes.
|
||||
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
|
||||
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
|
||||
selection.synchronize_unselected_volumes();
|
||||
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
|
||||
canvas->do_rotate(L("Reset Rotation"));
|
||||
|
@ -551,17 +551,23 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
m_new_position = volume->get_instance_offset();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
m_new_size = selection.get_scaled_instance_bounding_box().size();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
|
||||
#else
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_size = selection.get_scaled_instance_bounding_box().size();
|
||||
m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.0;
|
||||
}
|
||||
else {
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m_new_position = Vec3d::Zero();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
#else
|
||||
m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
|
||||
m_new_scale = volume->get_instance_scaling_factor() * 100.;
|
||||
m_new_scale = volume->get_instance_scaling_factor() * 100.0;
|
||||
}
|
||||
|
||||
m_new_enabled = true;
|
||||
|
@ -570,7 +576,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
m_new_position = box.center();
|
||||
m_new_rotation = Vec3d::Zero();
|
||||
m_new_scale = Vec3d(100., 100., 100.);
|
||||
m_new_scale = Vec3d(100.0, 100.0, 100.0);
|
||||
m_new_size = box.size();
|
||||
m_new_rotate_label_string = L("Rotate");
|
||||
m_new_scale_label_string = L("Scale");
|
||||
|
@ -586,7 +592,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
const Vec3d& offset = trafo.get_offset();
|
||||
const Vec3d& rotation = trafo.get_rotation();
|
||||
const Vec3d& scaling_factor = trafo.get_scaling_factor();
|
||||
const Vec3d& m = trafo.get_mirror();
|
||||
// const Vec3d& mirror = trafo.get_mirror();
|
||||
|
||||
m_new_position = offset;
|
||||
m_new_rotation = rotation * (180.0 / M_PI);
|
||||
|
@ -596,8 +602,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
|||
else {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
m_new_position = volume->get_volume_offset();
|
||||
m_new_rotation = volume->get_volume_rotation() * (180. / M_PI);
|
||||
m_new_scale = volume->get_volume_scaling_factor() * 100.;
|
||||
m_new_rotation = volume->get_volume_rotation() * (180.0 / M_PI);
|
||||
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
|
||||
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size()));
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
@ -712,11 +718,20 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
|
||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
Vec3d rotation = Vec3d::Zero();
|
||||
Vec3d scale = Vec3d::Ones();
|
||||
#else
|
||||
Vec3d rotation;
|
||||
Vec3d scale;
|
||||
double min_z = 0.;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
double min_z = 0.0;
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_full_instance() && m_world_coordinates) {
|
||||
#else
|
||||
if (selection.is_single_full_instance()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
rotation = volume->get_instance_rotation();
|
||||
scale = volume->get_instance_scaling_factor();
|
||||
min_z = wxGetApp().model().objects[volume->composite_id.object_id]->bounding_box().min.z();
|
||||
|
@ -728,7 +743,11 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
|||
}
|
||||
show_rotation = !rotation.isApprox(Vec3d::Zero());
|
||||
show_scale = !scale.isApprox(Vec3d::Ones());
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
show_drop_to_bed = min_z > EPSILON;
|
||||
#else
|
||||
show_drop_to_bed = std::abs(min_z) > SINKING_Z_THRESHOLD;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
|
||||
|
@ -1042,6 +1061,13 @@ void ObjectManipulation::set_world_coordinates(const bool world_coordinates)
|
|||
canvas->set_as_dirty();
|
||||
canvas->request_extra_frame();
|
||||
}
|
||||
|
||||
bool ObjectManipulation::get_world_coordinates() const
|
||||
{
|
||||
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
return wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier()) ?
|
||||
m_world_coordinates : true;
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
void ObjectManipulation::msw_rescale()
|
||||
|
|
|
@ -185,10 +185,11 @@ public:
|
|||
// Does the object manipulation panel work in World or Local coordinates?
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void set_world_coordinates(const bool world_coordinates);
|
||||
bool get_world_coordinates() const;
|
||||
#else
|
||||
void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); }
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
bool get_world_coordinates() const { return m_world_coordinates; }
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
void reset_cache() { m_cache.reset(); }
|
||||
#ifndef __APPLE__
|
||||
|
|
|
@ -24,27 +24,18 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam
|
|||
|
||||
std::string GLGizmoMove3D::get_tooltip() const
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const bool show_position = selection.is_single_full_instance();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates();
|
||||
Vec3d position = Vec3d::Zero();
|
||||
if (!world_coordinates) {
|
||||
if (selection.is_single_modifier() || selection.is_single_volume() || selection.is_wipe_tower())
|
||||
position = selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_offset();
|
||||
}
|
||||
else
|
||||
position = selection.get_bounding_box().center();
|
||||
|
||||
if (m_hover_id == 0)
|
||||
return m_grabbers[0].dragging ? "DX: " + format(m_displacement.x(), 2) : "X: " + format(position.x(), 2);
|
||||
return "X: " + format(m_displacement.x(), 2);
|
||||
else if (m_hover_id == 1)
|
||||
return m_grabbers[1].dragging ? "DY: " + format(m_displacement.y(), 2) : "Y: " + format(position.y(), 2);
|
||||
return "Y: " + format(m_displacement.y(), 2);
|
||||
else if (m_hover_id == 2)
|
||||
return m_grabbers[2].dragging ? "DZ: " + format(m_displacement.z(), 2) : "Z: " + format(position.z(), 2);
|
||||
return "Z: " + format(m_displacement.z(), 2);
|
||||
else
|
||||
return "";
|
||||
#else
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const bool show_position = selection.is_single_full_instance();
|
||||
const Vec3d& position = selection.get_bounding_box().center();
|
||||
|
||||
if (m_hover_id == 0 || m_grabbers[0].dragging)
|
||||
|
|
|
@ -60,9 +60,6 @@ protected:
|
|||
virtual bool on_is_activable() const override;
|
||||
virtual void on_start_dragging() override;
|
||||
virtual void on_stop_dragging() override;
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
virtual void on_start_dragging() override;
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
virtual void on_dragging(const UpdateData& data) override;
|
||||
virtual void on_render() override;
|
||||
virtual void on_render_for_picking() override;
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
#include "GLGizmoRotate.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
|
||||
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
|
||||
#include <GL/glew.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -99,6 +102,9 @@ bool GLGizmoRotate::on_init()
|
|||
|
||||
void GLGizmoRotate::on_start_dragging()
|
||||
{
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
init_data_from_selection(m_parent.get_selection());
|
||||
#else
|
||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||
m_center = box.center();
|
||||
m_radius = Offset + box.radius();
|
||||
|
@ -106,6 +112,7 @@ void GLGizmoRotate::on_start_dragging()
|
|||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
m_snap_fine_in_radius = m_radius;
|
||||
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
void GLGizmoRotate::on_dragging(const UpdateData &data)
|
||||
|
@ -154,12 +161,16 @@ void GLGizmoRotate::on_render()
|
|||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
|
||||
if (m_hover_id != 0 && !m_grabbers.front().dragging) {
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
init_data_from_selection(selection);
|
||||
#else
|
||||
m_center = box.center();
|
||||
m_radius = Offset + box.radius();
|
||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
m_snap_fine_in_radius = m_radius;
|
||||
m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
|
||||
|
@ -257,6 +268,24 @@ void GLGizmoRotate::on_render_for_picking()
|
|||
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void GLGizmoRotate::init_data_from_selection(const Selection& selection)
|
||||
{
|
||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
m_center = box.center();
|
||||
m_radius = Offset + box.radius();
|
||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
m_snap_fine_in_radius = m_radius;
|
||||
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
|
||||
|
||||
if (wxGetApp().obj_manipul()->get_world_coordinates())
|
||||
m_orient_matrix = Transform3d::Identity();
|
||||
else
|
||||
m_orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
|
@ -317,10 +346,10 @@ void GLGizmoRotate::render_circle() const
|
|||
#else
|
||||
::glBegin(GL_LINE_LOOP);
|
||||
for (unsigned int i = 0; i < ScaleStepsCount; ++i) {
|
||||
float angle = (float)i * ScaleStepRad;
|
||||
float x = ::cos(angle) * m_radius;
|
||||
float y = ::sin(angle) * m_radius;
|
||||
float z = 0.0f;
|
||||
const float angle = (float)i * ScaleStepRad;
|
||||
const float x = ::cos(angle) * m_radius;
|
||||
const float y = ::sin(angle) * m_radius;
|
||||
const float z = 0.0f;
|
||||
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||
}
|
||||
glsafe(::glEnd());
|
||||
|
@ -519,10 +548,10 @@ void GLGizmoRotate::render_angle() const
|
|||
#else
|
||||
::glBegin(GL_LINE_STRIP);
|
||||
for (unsigned int i = 0; i <= AngleResolution; ++i) {
|
||||
float angle = (float)i * step_angle;
|
||||
float x = ::cos(angle) * ex_radius;
|
||||
float y = ::sin(angle) * ex_radius;
|
||||
float z = 0.0f;
|
||||
const float angle = (float)i * step_angle;
|
||||
const float x = ::cos(angle) * ex_radius;
|
||||
const float y = ::sin(angle) * ex_radius;
|
||||
const float z = 0.0f;
|
||||
::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
|
||||
}
|
||||
glsafe(::glEnd());
|
||||
|
@ -687,10 +716,14 @@ void GLGizmoRotate::transform_to_local(const Selection& selection) const
|
|||
{
|
||||
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
glsafe(::glMultMatrixd(m_orient_matrix.data()));
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) {
|
||||
const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
|
||||
glsafe(::glMultMatrixd(orient_matrix.data()));
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
switch (m_axis)
|
||||
{
|
||||
|
@ -744,8 +777,12 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
|
|||
}
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m = m * m_orient_matrix.inverse();
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
||||
m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
m.translate(-m_center);
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ private:
|
|||
float m_snap_coarse_out_radius{ 0.0f };
|
||||
float m_snap_fine_in_radius{ 0.0f };
|
||||
float m_snap_fine_out_radius{ 0.0f };
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
Transform3d m_orient_matrix{ Transform3d::Identity() };
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#if !ENABLE_GIZMO_GRABBER_REFACTOR
|
||||
GLModel m_cone;
|
||||
|
@ -119,6 +122,10 @@ private:
|
|||
|
||||
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
|
||||
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void init_data_from_selection(const Selection& selection);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
};
|
||||
|
||||
class GLGizmoRotate3D : public GLGizmoBase
|
||||
|
|
|
@ -734,7 +734,7 @@ void Selection::translate(const Vec3d& displacement, bool local)
|
|||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (translation_type == Instance)
|
||||
synchronize_unselected_instances(SYNC_ROTATION_NONE);
|
||||
synchronize_unselected_instances(SyncRotationType::NONE);
|
||||
else if (translation_type == Volume)
|
||||
synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
@ -791,7 +791,18 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
}
|
||||
else {
|
||||
// extracts rotations from the composed transformation
|
||||
Vec3d new_rotation = transformation_type.world() ?
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
||||
const Vec3d new_rotation = transformation_type.world() ?
|
||||
Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
|
||||
transformation_type.absolute() ? rotation : Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix() * m);
|
||||
if (rot_axis_max == 2 && transformation_type.world() && transformation_type.joint()) {
|
||||
// Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
|
||||
const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), new_rotation);
|
||||
volume.set_instance_offset(m_cache.dragging_center + Eigen::AngleAxisd(z_diff, Vec3d::UnitZ()) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||
}
|
||||
#else
|
||||
const Vec3d new_rotation = transformation_type.world() ?
|
||||
Geometry::extract_euler_angles(Geometry::assemble_transform(Vec3d::Zero(), rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
|
||||
transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
|
||||
if (rot_axis_max == 2 && transformation_type.joint()) {
|
||||
|
@ -799,6 +810,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), new_rotation);
|
||||
volume.set_instance_offset(m_cache.dragging_center + Eigen::AngleAxisd(z_diff, Vec3d::UnitZ()) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
else if (!(m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center).isApprox(Vec3d::Zero()))
|
||||
volume.set_instance_offset(m_cache.dragging_center + Geometry::assemble_transform(Vec3d::Zero(), new_rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix().inverse() * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||
|
||||
|
@ -826,8 +838,8 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
rotate_instance(v, i);
|
||||
else if (m_mode == Volume) {
|
||||
// extracts rotations from the composed transformation
|
||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
||||
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
||||
const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
||||
const Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
||||
if (transformation_type.joint()) {
|
||||
const Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
|
||||
const Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
|
||||
|
@ -840,11 +852,24 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (m_mode == Instance) {
|
||||
SyncRotationType synch;
|
||||
if (transformation_type.world() && rot_axis_max == 2)
|
||||
synch = SyncRotationType::NONE;
|
||||
else if (transformation_type.local())
|
||||
synch = SyncRotationType::FULL;
|
||||
else
|
||||
synch = SyncRotationType::GENERAL;
|
||||
synchronize_unselected_instances(synch);
|
||||
}
|
||||
#else
|
||||
if (m_mode == Instance)
|
||||
synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
else if (m_mode == Volume)
|
||||
synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
}
|
||||
else { // it's the wipe tower that's selected and being rotated
|
||||
GLVolume& volume = *((*m_volumes)[*m_list.begin()]); // the wipe tower is always alone in the selection
|
||||
|
@ -887,7 +912,7 @@ void Selection::flattening_rotate(const Vec3d& normal)
|
|||
// Apply the same transformation also to other instances,
|
||||
// but respect their possibly diffrent z-rotation.
|
||||
if (m_mode == Instance)
|
||||
synchronize_unselected_instances(SYNC_ROTATION_GENERAL);
|
||||
synchronize_unselected_instances(SyncRotationType::GENERAL);
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
this->set_bounding_boxes_dirty();
|
||||
|
@ -950,7 +975,7 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
|
|||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Instance)
|
||||
synchronize_unselected_instances(SYNC_ROTATION_NONE);
|
||||
synchronize_unselected_instances(SyncRotationType::NONE);
|
||||
else if (m_mode == Volume)
|
||||
synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
@ -1063,7 +1088,7 @@ void Selection::mirror(Axis axis)
|
|||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Instance)
|
||||
synchronize_unselected_instances(SYNC_ROTATION_NONE);
|
||||
synchronize_unselected_instances(SyncRotationType::NONE);
|
||||
else if (m_mode == Volume)
|
||||
synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
@ -2528,7 +2553,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
|
|||
|
||||
assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()));
|
||||
switch (sync_rotation_type) {
|
||||
case SYNC_ROTATION_NONE: {
|
||||
case SyncRotationType::NONE: {
|
||||
// z only rotation -> synch instance z
|
||||
// The X,Y rotations should be synchronized from start to end of the rotation.
|
||||
assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation()));
|
||||
|
@ -2536,12 +2561,25 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
|
|||
v->set_instance_offset(Z, volume->get_instance_offset().z());
|
||||
break;
|
||||
}
|
||||
case SYNC_ROTATION_GENERAL:
|
||||
case SyncRotationType::GENERAL: {
|
||||
// generic rotation -> update instance z with the delta of the rotation.
|
||||
const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
|
||||
v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
|
||||
break;
|
||||
}
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
case SyncRotationType::FULL: {
|
||||
// generic rotation -> update instance z with the delta of the rotation.
|
||||
const Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rotation, m_cache.volumes_data[j].get_instance_rotation()));
|
||||
const Vec3d& axis = angle_axis.axis();
|
||||
const double z_diff = (std::abs(axis.x()) > EPSILON || std::abs(axis.y()) > EPSILON) ?
|
||||
angle_axis.angle() * axis.z() : Geometry::rotation_diff_z(rotation, m_cache.volumes_data[j].get_instance_rotation());
|
||||
|
||||
v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
|
||||
break;
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
|
||||
v->set_instance_scaling_factor(scaling_factor);
|
||||
v->set_instance_mirror(mirror);
|
||||
|
|
|
@ -389,11 +389,15 @@ private:
|
|||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
|
||||
public:
|
||||
enum SyncRotationType {
|
||||
enum class SyncRotationType {
|
||||
// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
|
||||
SYNC_ROTATION_NONE = 0,
|
||||
NONE = 0,
|
||||
// Synchronize after rotation by an axis not parallel with Z.
|
||||
SYNC_ROTATION_GENERAL = 1,
|
||||
GENERAL = 1,
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
// Fully synchronize rotation.
|
||||
FULL = 2,
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
};
|
||||
void synchronize_unselected_instances(SyncRotationType sync_rotation_type);
|
||||
void synchronize_unselected_volumes();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue