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:
enricoturri1966 2021-10-12 11:07:31 +02:00
parent 61e7eb4ade
commit ca5742c401
9 changed files with 155 additions and 54 deletions

View file

@ -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) {

View file

@ -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()

View file

@ -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__

View file

@ -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)

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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();