Another iteration on euler angles and instances synchronization

This commit is contained in:
Enrico Turri 2019-01-24 10:04:39 +01:00
parent 9a69305367
commit 9ca9e8dda5
2 changed files with 28 additions and 7 deletions

View file

@ -1182,19 +1182,27 @@ Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation,
Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix)
{
#if ENABLE_NEW_EULER_ANGLES
// see: http://www.gregslabaugh.net/publications/euler.pdf
// reference: http://www.gregslabaugh.net/publications/euler.pdf
auto is_approx = [](double value, double test_value) -> bool { return std::abs(value - test_value) < EPSILON; };
Vec3d angles1 = Vec3d::Zero();
Vec3d angles2 = Vec3d::Zero();
if (is_approx(std::abs(rotation_matrix(2, 0)), 1.0))
{
// the handling of singular cases deviates from the cited paper
// the following code works better when rotating an object with the gizmo after having
// changed its orientation using the place on bed gizmo
angles1(0) = 0.0;
angles1(1) = 0.5 * (double)PI;
angles1(2) = angles1(0) + ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2));
if (rotation_matrix(2, 0) > 0.0) // == +1.0
{
angles1(1) = 0.5 * (double)PI;
angles1(2) = angles1(0) + ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2));
}
else // == -1.0
{
angles1(1) = 0.5 * (double)PI;
angles1(2) = -angles1(0) - ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2));
}
angles2 = angles1;
}
else

View file

@ -2726,7 +2726,20 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(bool including_z)
if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx))
continue;
v->set_instance_rotation(Vec3d(rotation(0), rotation(1), including_z ? rotation(2) : m_cache.volumes_data[j].get_instance_rotation()(2) + rotation(2)));
auto is_approx = [](double value, double test_value) -> bool { return std::abs(value - test_value) < EPSILON; };
double z;
if (including_z)
// rotation comes from place on face -> force given z
z = rotation(2);
else if (is_approx(rotation(0), m_cache.volumes_data[j].get_instance_rotation()(0)) && is_approx(rotation(1), m_cache.volumes_data[j].get_instance_rotation()(1)))
// z only rotation -> keep instance z
z = v->get_instance_rotation()(2);
else
// generic rotation -> update instance z
z = m_cache.volumes_data[j].get_instance_rotation()(2) + rotation(2);
v->set_instance_rotation(Vec3d(rotation(0), rotation(1), z));
v->set_instance_scaling_factor(scaling_factor);
v->set_instance_mirror(mirror);