Merge remote-tracking branch 'origin/vb_et_instances_synch'
This commit is contained in:
commit
f43c493731
@ -872,18 +872,15 @@ Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
||||||
double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
double rotation_diff_z(const Transform3d &trafo_from, const Transform3d &trafo_to)
|
||||||
{
|
{
|
||||||
const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
auto m = trafo_to.linear() * trafo_from.linear().inverse();
|
||||||
const Vec3d& axis = angle_axis.axis();
|
assert(std::abs(m.determinant() - 1) < EPSILON);
|
||||||
const double angle = angle_axis.angle();
|
Vec3d vx = m * Vec3d(1., 0., 0);
|
||||||
#ifndef NDEBUG
|
// Verify that the linear part of rotation from trafo_from to trafo_to rotates around Z and is unity.
|
||||||
if (std::abs(angle) > 1e-8) {
|
assert(std::abs(std::hypot(vx.x(), vx.y()) - 1.) < 1e-5);
|
||||||
assert(std::abs(axis.x()) < 1e-8);
|
assert(std::abs(vx.z()) < 1e-5);
|
||||||
assert(std::abs(axis.y()) < 1e-8);
|
return atan2(vx.y(), vx.x());
|
||||||
}
|
|
||||||
#endif /* NDEBUG */
|
|
||||||
return (axis.z() < 0) ? -angle : angle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace Slic3r::Geometry
|
}} // namespace Slic3r::Geometry
|
||||||
|
@ -470,8 +470,7 @@ public:
|
|||||||
Transform3d get_mirror_matrix() const;
|
Transform3d get_mirror_matrix() const;
|
||||||
|
|
||||||
bool is_left_handed() const {
|
bool is_left_handed() const {
|
||||||
const Vec3d mirror = get_mirror();
|
return m_matrix.affine().determinant() < 0;
|
||||||
return mirror.x() * mirror.y() * mirror.z() < 0.0;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
bool is_scaling_uniform() const { return std::abs(m_scaling_factor.x() - m_scaling_factor.y()) < 1e-8 && std::abs(m_scaling_factor.x() - m_scaling_factor.z()) < 1e-8; }
|
bool is_scaling_uniform() const { return std::abs(m_scaling_factor.x() - m_scaling_factor.y()) < 1e-8 && std::abs(m_scaling_factor.x() - m_scaling_factor.z()) < 1e-8; }
|
||||||
@ -547,7 +546,7 @@ extern Transform3d transform3d_from_string(const std::string& transform_str);
|
|||||||
extern Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to);
|
extern Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to);
|
||||||
// Rotation by Z to align rot_xyz_from to rot_xyz_to.
|
// Rotation by Z to align rot_xyz_from to rot_xyz_to.
|
||||||
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
||||||
extern double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to);
|
extern double rotation_diff_z(const Transform3d &trafo_from, const Transform3d &trafo_to);
|
||||||
|
|
||||||
// Is the angle close to a multiple of 90 degrees?
|
// Is the angle close to a multiple of 90 degrees?
|
||||||
inline bool is_rotation_ninety_degrees(double a)
|
inline bool is_rotation_ninety_degrees(double a)
|
||||||
|
@ -1780,7 +1780,7 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
|
|||||||
// Adjust the instances.
|
// Adjust the instances.
|
||||||
for (size_t i = 0; i < this->instances.size(); ++ i) {
|
for (size_t i = 0; i < this->instances.size(); ++ i) {
|
||||||
ModelInstance &model_instance = *this->instances[i];
|
ModelInstance &model_instance = *this->instances[i];
|
||||||
model_instance.set_rotation(Vec3d(0., 0., Geometry::rotation_diff_z(reference_trafo.get_rotation(), model_instance.get_rotation())));
|
model_instance.set_rotation(Vec3d(0., 0., Geometry::rotation_diff_z(reference_trafo.get_matrix(), model_instance.get_matrix())));
|
||||||
model_instance.set_scaling_factor(Vec3d(new_scaling_factor, new_scaling_factor, new_scaling_factor));
|
model_instance.set_scaling_factor(Vec3d(new_scaling_factor, new_scaling_factor, new_scaling_factor));
|
||||||
model_instance.set_mirror(Vec3d(1., 1., 1.));
|
model_instance.set_mirror(Vec3d(1., 1., 1.));
|
||||||
}
|
}
|
||||||
|
@ -405,7 +405,7 @@ bool Print::sequential_print_horizontal_clearance_valid(const Print& print, Poly
|
|||||||
}
|
}
|
||||||
// Make a copy, so it may be rotated for instances.
|
// Make a copy, so it may be rotated for instances.
|
||||||
Polygon convex_hull0 = it_convex_hull->second;
|
Polygon convex_hull0 = it_convex_hull->second;
|
||||||
const double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation());
|
const double z_diff = Geometry::rotation_diff_z(model_instance0->get_matrix(), print_object->instances().front().model_instance->get_matrix());
|
||||||
if (std::abs(z_diff) > EPSILON)
|
if (std::abs(z_diff) > EPSILON)
|
||||||
convex_hull0.rotate(z_diff);
|
convex_hull0.rotate(z_diff);
|
||||||
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||||
|
@ -76,8 +76,8 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transfor
|
|||||||
BoundingBoxf3 bbox = model_object->raw_bounding_box();
|
BoundingBoxf3 bbox = model_object->raw_bounding_box();
|
||||||
Vec3d bbox_center = bbox.center();
|
Vec3d bbox_center = bbox.center();
|
||||||
// We may need to rotate the bbox / bbox_center from the original instance to the current instance.
|
// We may need to rotate the bbox / bbox_center from the original instance to the current instance.
|
||||||
double z_diff = Geometry::rotation_diff_z(model_object->instances.front()->get_rotation(), instances.front().model_instance->get_rotation());
|
double z_diff = Geometry::rotation_diff_z(model_object->instances.front()->get_matrix(), instances.front().model_instance->get_matrix());
|
||||||
if (std::abs(z_diff) > EPSILON) {
|
if (std::abs(z_diff) > EPSILON) {
|
||||||
auto z_rot = Eigen::AngleAxisd(z_diff, Vec3d::UnitZ());
|
auto z_rot = Eigen::AngleAxisd(z_diff, Vec3d::UnitZ());
|
||||||
bbox = bbox.transformed(Transform3d(z_rot));
|
bbox = bbox.transformed(Transform3d(z_rot));
|
||||||
bbox_center = (z_rot * bbox_center).eval();
|
bbox_center = (z_rot * bbox_center).eval();
|
||||||
|
@ -190,14 +190,13 @@ static std::vector<SLAPrintObject::Instance> sla_instances(const ModelObject &mo
|
|||||||
std::vector<SLAPrintObject::Instance> instances;
|
std::vector<SLAPrintObject::Instance> instances;
|
||||||
assert(! model_object.instances.empty());
|
assert(! model_object.instances.empty());
|
||||||
if (! model_object.instances.empty()) {
|
if (! model_object.instances.empty()) {
|
||||||
Vec3d rotation0 = model_object.instances.front()->get_rotation();
|
const Transform3d& trafo0 = model_object.instances.front()->get_matrix();
|
||||||
rotation0(2) = 0.;
|
|
||||||
for (ModelInstance *model_instance : model_object.instances)
|
for (ModelInstance *model_instance : model_object.instances)
|
||||||
if (model_instance->is_printable()) {
|
if (model_instance->is_printable()) {
|
||||||
instances.emplace_back(
|
instances.emplace_back(
|
||||||
model_instance->id(),
|
model_instance->id(),
|
||||||
Point::new_scale(model_instance->get_offset(X), model_instance->get_offset(Y)),
|
Point::new_scale(model_instance->get_offset(X), model_instance->get_offset(Y)),
|
||||||
float(Geometry::rotation_diff_z(rotation0, model_instance->get_rotation())));
|
float(Geometry::rotation_diff_z(trafo0, model_instance->get_matrix())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return instances;
|
return instances;
|
||||||
|
@ -2852,6 +2852,16 @@ void Selection::render_debug_window() const
|
|||||||
}
|
}
|
||||||
#endif // ENABLE_WORLD_COORDINATE_DEBUG
|
#endif // ENABLE_WORLD_COORDINATE_DEBUG
|
||||||
|
|
||||||
|
static bool is_left_handed(const Transform3d::ConstLinearPart& m)
|
||||||
|
{
|
||||||
|
return m.determinant() < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_left_handed(const Transform3d& m)
|
||||||
|
{
|
||||||
|
return is_left_handed(m.linear());
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||||
{
|
{
|
||||||
@ -2866,6 +2876,7 @@ static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &
|
|||||||
return std::abs(axis.x()) < 1e-8 && std::abs(axis.y()) < 1e-8 && std::abs(std::abs(axis.z()) - 1.) < 1e-8;
|
return std::abs(axis.x()) < 1e-8 && std::abs(axis.y()) < 1e-8 && std::abs(std::abs(axis.z()) - 1.) < 1e-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes)
|
static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes)
|
||||||
{
|
{
|
||||||
for (int idx_object = 0; idx_object < int(model.objects.size()); ++idx_object) {
|
for (int idx_object = 0; idx_object < int(model.objects.size()); ++idx_object) {
|
||||||
@ -2887,8 +2898,103 @@ static void verify_instances_rotation_synchronized(const Model &model, const GLV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool is_rotation_xy_synchronized(const Transform3d::ConstLinearPart &trafo_from, const Transform3d::ConstLinearPart &trafo_to)
|
||||||
|
{
|
||||||
|
auto rot = trafo_to * trafo_from.inverse();
|
||||||
|
static constexpr const double eps = EPSILON;
|
||||||
|
return
|
||||||
|
// Looks like a rotation around Z: block(0..1, 0..1) + no change of Z component.
|
||||||
|
is_approx(rot(0, 0), rot(1, 1), eps) &&
|
||||||
|
is_approx(rot(0, 1), - rot(1, 0), eps) &&
|
||||||
|
is_approx(rot(2, 2), 1., eps) &&
|
||||||
|
// Rest should be zeros.
|
||||||
|
is_approx(rot(0, 2), 0., eps) &&
|
||||||
|
is_approx(rot(1, 2), 0., eps) &&
|
||||||
|
is_approx(rot(2, 0), 0., eps) &&
|
||||||
|
is_approx(rot(2, 1), 0., eps) &&
|
||||||
|
// Determinant equals 1
|
||||||
|
is_approx(rot.determinant(), 1., eps) &&
|
||||||
|
// and finally the rotated X and Y axes shall be perpendicular.
|
||||||
|
is_approx(rot(0, 0) * rot(0, 1) + rot(1, 0) * rot(1, 1), 0., eps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_rotation_xy_synchronized(const Transform3d& trafo_from, const Transform3d& trafo_to)
|
||||||
|
{
|
||||||
|
return is_rotation_xy_synchronized(trafo_from.linear(), trafo_to.linear());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes)
|
||||||
|
{
|
||||||
|
for (int idx_object = 0; idx_object < int(model.objects.size()); ++idx_object) {
|
||||||
|
int idx_volume_first = -1;
|
||||||
|
for (int i = 0; i < (int)volumes.size(); ++i) {
|
||||||
|
if (volumes[i]->object_idx() == idx_object) {
|
||||||
|
idx_volume_first = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(idx_volume_first != -1); // object without instances?
|
||||||
|
if (idx_volume_first == -1)
|
||||||
|
continue;
|
||||||
|
const Transform3d::ConstLinearPart &rotation0 = volumes[idx_volume_first]->get_instance_transformation().get_matrix().linear();
|
||||||
|
for (int i = idx_volume_first + 1; i < (int)volumes.size(); ++i)
|
||||||
|
if (volumes[i]->object_idx() == idx_object) {
|
||||||
|
const Transform3d::ConstLinearPart &rotation = volumes[i]->get_instance_transformation().get_matrix().linear();
|
||||||
|
assert(is_rotation_xy_synchronized(rotation, rotation0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_type)
|
||||||
|
{
|
||||||
|
std::set<unsigned int> done; // prevent processing volumes twice
|
||||||
|
done.insert(m_list.begin(), m_list.end());
|
||||||
|
for (unsigned int i : m_list) {
|
||||||
|
if (done.size() == m_volumes->size())
|
||||||
|
break;
|
||||||
|
const GLVolume* volume_i = (*m_volumes)[i];
|
||||||
|
if (volume_i->is_wipe_tower)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const int object_idx = volume_i->object_idx();
|
||||||
|
const int instance_idx = volume_i->instance_idx();
|
||||||
|
const Transform3d& curr_inst_trafo_i = volume_i->get_instance_transformation().get_matrix();
|
||||||
|
const bool curr_inst_left_handed = is_left_handed(curr_inst_trafo_i);
|
||||||
|
const Transform3d& old_inst_trafo_i = m_cache.volumes_data[i].get_instance_transform().get_matrix();
|
||||||
|
bool mirrored = is_left_handed(curr_inst_trafo_i) != is_left_handed(old_inst_trafo_i);
|
||||||
|
// bool mirrored = curr_inst_trafo_i.linear().determinant() * old_inst_trafo_i.linear().determinant() < 0;
|
||||||
|
|
||||||
|
// Process unselected instances.
|
||||||
|
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
|
||||||
|
if (done.size() == m_volumes->size())
|
||||||
|
break;
|
||||||
|
if (done.find(j) != done.end())
|
||||||
|
continue;
|
||||||
|
GLVolume* volume_j = (*m_volumes)[j];
|
||||||
|
if (volume_j->object_idx() != object_idx || volume_j->instance_idx() == instance_idx)
|
||||||
|
continue;
|
||||||
|
const Transform3d& old_inst_trafo_j = m_cache.volumes_data[j].get_instance_transform().get_matrix();
|
||||||
|
assert(is_rotation_xy_synchronized(old_inst_trafo_i, old_inst_trafo_j));
|
||||||
|
Transform3d new_inst_trafo_j = volume_j->get_instance_transformation().get_matrix();
|
||||||
|
if (sync_rotation_type != SyncRotationType::NONE || mirrored)
|
||||||
|
new_inst_trafo_j.linear() = (old_inst_trafo_j.linear() * old_inst_trafo_i.linear().inverse()) * curr_inst_trafo_i.linear();
|
||||||
|
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||||
|
new_inst_trafo_j.translation().z() = curr_inst_trafo_i.translation().z();
|
||||||
|
assert(is_rotation_xy_synchronized(curr_inst_trafo_i, new_inst_trafo_j));
|
||||||
|
volume_j->set_instance_transformation(new_inst_trafo_j);
|
||||||
|
done.insert(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
verify_instances_rotation_synchronized(*m_model, *m_volumes);
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
}
|
||||||
|
#else
|
||||||
void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_type)
|
void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_type)
|
||||||
{
|
{
|
||||||
std::set<unsigned int> done; // prevent processing volumes twice
|
std::set<unsigned int> done; // prevent processing volumes twice
|
||||||
@ -2904,17 +3010,9 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
|
|||||||
|
|
||||||
const int object_idx = volume_i->object_idx();
|
const int object_idx = volume_i->object_idx();
|
||||||
const int instance_idx = volume_i->instance_idx();
|
const int instance_idx = volume_i->instance_idx();
|
||||||
#if ENABLE_WORLD_COORDINATE
|
|
||||||
const Geometry::Transformation& curr_inst_trafo_i = volume_i->get_instance_transformation();
|
|
||||||
const Vec3d curr_inst_rotation_i = curr_inst_trafo_i.get_rotation();
|
|
||||||
const Vec3d& curr_inst_scaling_factor_i = curr_inst_trafo_i.get_scaling_factor();
|
|
||||||
const Vec3d& curr_inst_mirror_i = curr_inst_trafo_i.get_mirror();
|
|
||||||
const Vec3d old_inst_rotation_i = m_cache.volumes_data[i].get_instance_transform().get_rotation();
|
|
||||||
#else
|
|
||||||
const Vec3d& rotation = volume_i->get_instance_rotation();
|
const Vec3d& rotation = volume_i->get_instance_rotation();
|
||||||
const Vec3d& scaling_factor = volume_i->get_instance_scaling_factor();
|
const Vec3d& scaling_factor = volume_i->get_instance_scaling_factor();
|
||||||
const Vec3d& mirror = volume_i->get_instance_mirror();
|
const Vec3d& mirror = volume_i->get_instance_mirror();
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
|
||||||
|
|
||||||
// Process unselected instances.
|
// Process unselected instances.
|
||||||
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
|
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
|
||||||
@ -2928,64 +3026,27 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
|
|||||||
if (volume_j->object_idx() != object_idx || volume_j->instance_idx() == instance_idx)
|
if (volume_j->object_idx() != object_idx || volume_j->instance_idx() == instance_idx)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if ENABLE_WORLD_COORDINATE
|
|
||||||
const Vec3d old_inst_rotation_j = m_cache.volumes_data[j].get_instance_transform().get_rotation();
|
|
||||||
assert(is_rotation_xy_synchronized(old_inst_rotation_i, old_inst_rotation_j));
|
|
||||||
const Geometry::Transformation& curr_inst_trafo_j = volume_j->get_instance_transformation();
|
|
||||||
const Vec3d curr_inst_rotation_j = curr_inst_trafo_j.get_rotation();
|
|
||||||
Vec3d new_inst_offset_j = curr_inst_trafo_j.get_offset();
|
|
||||||
Vec3d new_inst_rotation_j = curr_inst_rotation_j;
|
|
||||||
#else
|
|
||||||
assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()));
|
assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()));
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
|
||||||
|
|
||||||
switch (sync_rotation_type) {
|
switch (sync_rotation_type) {
|
||||||
case SyncRotationType::NONE: {
|
case SyncRotationType::NONE: {
|
||||||
// z only rotation -> synch instance z
|
// z only rotation -> synch instance z
|
||||||
// The X,Y rotations should be synchronized from start to end of the rotation.
|
// The X,Y rotations should be synchronized from start to end of the rotation.
|
||||||
#if ENABLE_WORLD_COORDINATE
|
|
||||||
assert(is_rotation_xy_synchronized(curr_inst_rotation_i, curr_inst_rotation_j));
|
|
||||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
|
||||||
new_inst_offset_j.z() = curr_inst_trafo_i.get_offset().z();
|
|
||||||
#else
|
|
||||||
assert(is_rotation_xy_synchronized(rotation, volume_j->get_instance_rotation()));
|
assert(is_rotation_xy_synchronized(rotation, volume_j->get_instance_rotation()));
|
||||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||||
volume_j->set_instance_offset(Z, volume_i->get_instance_offset().z());
|
volume_j->set_instance_offset(Z, volume_i->get_instance_offset().z());
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SyncRotationType::GENERAL: {
|
case SyncRotationType::GENERAL: {
|
||||||
// generic rotation -> update instance z with the delta of the rotation.
|
// generic rotation -> update instance z with the delta of the rotation.
|
||||||
#if ENABLE_WORLD_COORDINATE
|
|
||||||
const double z_diff = Geometry::rotation_diff_z(old_inst_rotation_i, old_inst_rotation_j);
|
|
||||||
new_inst_rotation_j = curr_inst_rotation_i + z_diff * Vec3d::UnitZ();
|
|
||||||
#else
|
|
||||||
const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_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());
|
||||||
volume_j->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
|
volume_j->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
|
||||||
break;
|
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(curr_inst_rotation_i, old_inst_rotation_j));
|
|
||||||
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(curr_inst_rotation_i, old_inst_rotation_j);
|
|
||||||
|
|
||||||
new_inst_rotation_j = curr_inst_rotation_i + z_diff * Vec3d::UnitZ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_WORLD_COORDINATE
|
|
||||||
volume_j->set_instance_transformation(Geometry::assemble_transform(new_inst_offset_j, new_inst_rotation_j,
|
|
||||||
curr_inst_scaling_factor_i, curr_inst_mirror_i));
|
|
||||||
#else
|
|
||||||
volume_j->set_instance_scaling_factor(scaling_factor);
|
volume_j->set_instance_scaling_factor(scaling_factor);
|
||||||
volume_j->set_instance_mirror(mirror);
|
volume_j->set_instance_mirror(mirror);
|
||||||
#endif // ENABLE_WORLD_COORDINATE
|
|
||||||
|
|
||||||
done.insert(j);
|
done.insert(j);
|
||||||
}
|
}
|
||||||
@ -2995,6 +3056,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
|
|||||||
verify_instances_rotation_synchronized(*m_model, *m_volumes);
|
verify_instances_rotation_synchronized(*m_model, *m_volumes);
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
|
||||||
void Selection::synchronize_unselected_volumes()
|
void Selection::synchronize_unselected_volumes()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user