Tech ENABLE_ALLOW_NEGATIVE_Z-> Synchronize sinking instances

This commit is contained in:
enricoturri1966 2021-05-05 11:53:24 +02:00
parent 3f6123e653
commit bb18edde0a
2 changed files with 79 additions and 101 deletions

View file

@ -58,13 +58,11 @@ bool Selection::Clipboard::is_sla_compliant() const
if (m_mode == Selection::Volume) if (m_mode == Selection::Volume)
return false; return false;
for (const ModelObject* o : m_model->objects) for (const ModelObject* o : m_model->objects) {
{
if (o->is_multiparts()) if (o->is_multiparts())
return false; return false;
for (const ModelVolume* v : o->volumes) for (const ModelVolume* v : o->volumes) {
{
if (v->is_modifier()) if (v->is_modifier())
return false; return false;
} }
@ -78,7 +76,8 @@ Selection::Clipboard::Clipboard()
m_model.reset(new Model); m_model.reset(new Model);
} }
void Selection::Clipboard::reset() { void Selection::Clipboard::reset()
{
m_model->clear_objects(); m_model->clear_objects();
} }
@ -149,7 +148,7 @@ void Selection::set_model(Model* model)
void Selection::add(unsigned int volume_idx, bool as_single_selection, bool check_for_already_contained) void Selection::add(unsigned int volume_idx, bool as_single_selection, bool check_for_already_contained)
{ {
if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx)) if (!m_valid || (unsigned int)m_volumes->size() <= volume_idx)
return; return;
const GLVolume* volume = (*m_volumes)[volume_idx]; const GLVolume* volume = (*m_volumes)[volume_idx];
@ -167,8 +166,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec
needs_reset |= as_single_selection && !is_any_modifier() && volume->is_modifier; needs_reset |= as_single_selection && !is_any_modifier() && volume->is_modifier;
needs_reset |= is_any_modifier() && !volume->is_modifier; needs_reset |= is_any_modifier() && !volume->is_modifier;
if (!already_contained || needs_reset) if (!already_contained || needs_reset) {
{
wxGetApp().plater()->take_snapshot(_L("Selection-Add")); wxGetApp().plater()->take_snapshot(_L("Selection-Add"));
if (needs_reset) if (needs_reset)
@ -185,7 +183,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec
{ {
case Volume: case Volume:
{ {
if ((volume->volume_idx() >= 0) && (is_empty() || (volume->instance_idx() == get_instance_idx()))) if (volume->volume_idx() >= 0 && (is_empty() || volume->instance_idx() == get_instance_idx()))
do_add_volume(volume_idx); do_add_volume(volume_idx);
break; break;
@ -204,7 +202,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec
void Selection::remove(unsigned int volume_idx) void Selection::remove(unsigned int volume_idx)
{ {
if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx)) if (!m_valid || (unsigned int)m_volumes->size() <= volume_idx)
return; return;
if (!contains_volume(volume_idx)) if (!contains_volume(volume_idx))
@ -333,10 +331,9 @@ void Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx)
if (!m_valid) if (!m_valid)
return; return;
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
{
GLVolume* v = (*m_volumes)[i]; GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() == (int)object_idx) && (v->volume_idx() == (int)volume_idx)) if (v->object_idx() == (int)object_idx && v->volume_idx() == (int)volume_idx)
do_remove_volume(i); do_remove_volume(i);
} }
@ -358,8 +355,7 @@ void Selection::add_volumes(EMode mode, const std::vector<unsigned int>& volume_
clear(); clear();
m_mode = mode; m_mode = mode;
for (unsigned int i : volume_idxs) for (unsigned int i : volume_idxs) {
{
if (i < (unsigned int)m_volumes->size()) if (i < (unsigned int)m_volumes->size())
do_add_volume(i); do_add_volume(i);
} }
@ -374,8 +370,7 @@ void Selection::remove_volumes(EMode mode, const std::vector<unsigned int>& volu
return; return;
m_mode = mode; m_mode = mode;
for (unsigned int i : volume_idxs) for (unsigned int i : volume_idxs) {
{
if (i < (unsigned int)m_volumes->size()) if (i < (unsigned int)m_volumes->size())
do_remove_volume(i); do_remove_volume(i);
} }
@ -390,8 +385,7 @@ void Selection::add_all()
return; return;
unsigned int count = 0; unsigned int count = 0;
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
{
if (!(*m_volumes)[i]->is_wipe_tower) if (!(*m_volumes)[i]->is_wipe_tower)
++count; ++count;
} }
@ -404,8 +398,7 @@ void Selection::add_all()
m_mode = Instance; m_mode = Instance;
clear(); clear();
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
{
if (!(*m_volumes)[i]->is_wipe_tower) if (!(*m_volumes)[i]->is_wipe_tower)
do_add_volume(i); do_add_volume(i);
} }
@ -455,8 +448,7 @@ void Selection::clear()
if (m_list.empty()) if (m_list.empty())
return; return;
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
(*m_volumes)[i]->selected = false; (*m_volumes)[i]->selected = false;
} }
@ -522,16 +514,15 @@ bool Selection::is_single_full_instance() const
return false; return false;
int object_idx = m_valid ? get_object_idx() : -1; int object_idx = m_valid ? get_object_idx() : -1;
if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx)) if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
return false; return false;
int instance_idx = (*m_volumes)[*m_list.begin()]->instance_idx(); int instance_idx = (*m_volumes)[*m_list.begin()]->instance_idx();
std::set<int> volumes_idxs; std::set<int> volumes_idxs;
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
const GLVolume* v = (*m_volumes)[i]; const GLVolume* v = (*m_volumes)[i];
if ((object_idx != v->object_idx()) || (instance_idx != v->instance_idx())) if (object_idx != v->object_idx() || instance_idx != v->instance_idx())
return false; return false;
int volume_idx = v->volume_idx(); int volume_idx = v->volume_idx();
@ -544,8 +535,8 @@ bool Selection::is_single_full_instance() const
bool Selection::is_from_single_object() const bool Selection::is_from_single_object() const
{ {
int idx = get_object_idx(); const int idx = get_object_idx();
return (0 <= idx) && (idx < 1000); return 0 <= idx && idx < 1000;
} }
bool Selection::is_sla_compliant() const bool Selection::is_sla_compliant() const
@ -553,8 +544,7 @@ bool Selection::is_sla_compliant() const
if (m_mode == Volume) if (m_mode == Volume)
return false; return false;
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
if ((*m_volumes)[i]->is_modifier) if ((*m_volumes)[i]->is_modifier)
return false; return false;
} }
@ -564,8 +554,7 @@ bool Selection::is_sla_compliant() const
bool Selection::contains_all_volumes(const std::vector<unsigned int>& volume_idxs) const bool Selection::contains_all_volumes(const std::vector<unsigned int>& volume_idxs) const
{ {
for (unsigned int i : volume_idxs) for (unsigned int i : volume_idxs) {
{
if (m_list.find(i) == m_list.end()) if (m_list.find(i) == m_list.end())
return false; return false;
} }
@ -575,8 +564,7 @@ bool Selection::contains_all_volumes(const std::vector<unsigned int>& volume_idx
bool Selection::contains_any_volume(const std::vector<unsigned int>& volume_idxs) const bool Selection::contains_any_volume(const std::vector<unsigned int>& volume_idxs) const
{ {
for (unsigned int i : volume_idxs) for (unsigned int i : volume_idxs) {
{
if (m_list.find(i) != m_list.end()) if (m_list.find(i) != m_list.end())
return true; return true;
} }
@ -588,8 +576,7 @@ bool Selection::matches(const std::vector<unsigned int>& volume_idxs) const
{ {
unsigned int count = 0; unsigned int count = 0;
for (unsigned int i : volume_idxs) for (unsigned int i : volume_idxs) {
{
if (m_list.find(i) != m_list.end()) if (m_list.find(i) != m_list.end())
++count; ++count;
else else
@ -614,8 +601,7 @@ int Selection::get_object_idx() const
int Selection::get_instance_idx() const int Selection::get_instance_idx() const
{ {
if (m_cache.content.size() == 1) if (m_cache.content.size() == 1) {
{
const InstanceIdxsList& idxs = m_cache.content.begin()->second; const InstanceIdxsList& idxs = m_cache.content.begin()->second;
if (idxs.size() == 1) if (idxs.size() == 1)
return *idxs.begin(); return *idxs.begin();
@ -673,12 +659,11 @@ void Selection::translate(const Vec3d& displacement, bool local)
EMode translation_type = m_mode; EMode translation_type = m_mode;
for (unsigned int i : m_list) { for (unsigned int i : m_list) {
if (m_mode == Volume || (*m_volumes)[i]->is_wipe_tower) if (m_mode == Volume || (*m_volumes)[i]->is_wipe_tower) {
{
if (local) if (local)
(*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement); (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement);
else { else {
Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
(*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
} }
} }
@ -686,7 +671,7 @@ void Selection::translate(const Vec3d& displacement, bool local)
if (is_from_fully_selected_instance(i)) if (is_from_fully_selected_instance(i))
(*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement);
else { else {
Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
(*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
translation_type = Volume; translation_type = Volume;
} }
@ -714,18 +699,14 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
if (!is_wipe_tower()) { if (!is_wipe_tower()) {
int rot_axis_max = 0; int rot_axis_max = 0;
if (rotation.isApprox(Vec3d::Zero())) if (rotation.isApprox(Vec3d::Zero())) {
{ for (unsigned int i : m_list) {
for (unsigned int i : m_list)
{
GLVolume &volume = *(*m_volumes)[i]; GLVolume &volume = *(*m_volumes)[i];
if (m_mode == Instance) if (m_mode == Instance) {
{
volume.set_instance_rotation(m_cache.volumes_data[i].get_instance_rotation()); volume.set_instance_rotation(m_cache.volumes_data[i].get_instance_rotation());
volume.set_instance_offset(m_cache.volumes_data[i].get_instance_position()); volume.set_instance_offset(m_cache.volumes_data[i].get_instance_position());
} }
else if (m_mode == Volume) else if (m_mode == Volume) {
{
volume.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation()); volume.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation());
volume.set_volume_offset(m_cache.volumes_data[i].get_volume_position()); volume.set_volume_offset(m_cache.volumes_data[i].get_volume_position());
} }
@ -742,14 +723,14 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
// For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it. // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it.
std::vector<int> object_instance_first(m_model->objects.size(), -1); std::vector<int> object_instance_first(m_model->objects.size(), -1);
auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) { auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) {
int first_volume_idx = object_instance_first[volume.object_idx()]; const int first_volume_idx = object_instance_first[volume.object_idx()];
if (rot_axis_max != 2 && first_volume_idx != -1) { if (rot_axis_max != 2 && first_volume_idx != -1) {
// Generic rotation, but no rotation around the Z axis. // Generic rotation, but no rotation around the Z axis.
// Always do a local rotation (do not consider the selection to be a rigid body). // Always do a local rotation (do not consider the selection to be a rigid body).
assert(is_approx(rotation.z(), 0.0)); assert(is_approx(rotation.z(), 0.0));
const GLVolume &first_volume = *(*m_volumes)[first_volume_idx]; const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
const Vec3d &rotation = first_volume.get_instance_rotation(); const Vec3d &rotation = first_volume.get_instance_rotation();
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation()); const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff)); volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
} }
else { else {
@ -759,7 +740,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation(); transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
if (rot_axis_max == 2 && transformation_type.joint()) { if (rot_axis_max == 2 && transformation_type.joint()) {
// Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis. // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), new_rotation); 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)); 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));
} }
volume.set_instance_rotation(new_rotation); volume.set_instance_rotation(new_rotation);
@ -767,19 +748,16 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
} }
}; };
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
GLVolume &volume = *(*m_volumes)[i]; GLVolume &volume = *(*m_volumes)[i];
if (is_single_full_instance()) if (is_single_full_instance())
rotate_instance(volume, i); rotate_instance(volume, i);
else if (is_single_volume() || is_single_modifier()) else if (is_single_volume() || is_single_modifier()) {
{
if (transformation_type.independent()) if (transformation_type.independent())
volume.set_volume_rotation(volume.get_volume_rotation() + rotation); volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
else else {
{ const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
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());
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
volume.set_volume_rotation(new_rotation); volume.set_volume_rotation(new_rotation);
} }
} }
@ -787,15 +765,13 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
{ {
if (m_mode == Instance) if (m_mode == Instance)
rotate_instance(volume, i); rotate_instance(volume, i);
else if (m_mode == Volume) else if (m_mode == Volume) {
{
// extracts rotations from the composed transformation // extracts rotations from the composed transformation
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); 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()); Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
if (transformation_type.joint()) if (transformation_type.joint()) {
{ const Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
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);
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
volume.set_volume_offset(local_pivot + offset); volume.set_volume_offset(local_pivot + offset);
} }
volume.set_volume_rotation(new_rotation); volume.set_volume_rotation(new_rotation);
@ -816,8 +792,8 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
// make sure the wipe tower rotates around its center, not origin // make sure the wipe tower rotates around its center, not origin
// we can assume that only Z rotation changes // we can assume that only Z rotation changes
Vec3d center_local = volume.transformed_bounding_box().center() - volume.get_volume_offset(); const Vec3d center_local = volume.transformed_bounding_box().center() - volume.get_volume_offset();
Vec3d center_local_new = Eigen::AngleAxisd(rotation(2)-volume.get_volume_rotation()(2), Vec3d(0, 0, 1)) * center_local; const Vec3d center_local_new = Eigen::AngleAxisd(rotation(2)-volume.get_volume_rotation()(2), Vec3d(0.0, 0.0, 1.0)) * center_local;
volume.set_volume_rotation(rotation); volume.set_volume_rotation(rotation);
volume.set_volume_offset(volume.get_volume_offset() + center_local - center_local_new); volume.set_volume_offset(volume.get_volume_offset() + center_local - center_local_new);
} }
@ -835,8 +811,7 @@ void Selection::flattening_rotate(const Vec3d& normal)
if (!m_valid) if (!m_valid)
return; return;
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
// Normal transformed from the object coordinate space to the world coordinate space. // Normal transformed from the object coordinate space to the world coordinate space.
const auto &voldata = m_cache.volumes_data[i]; const auto &voldata = m_cache.volumes_data[i];
Vec3d tnormal = (Geometry::assemble_transform( Vec3d tnormal = (Geometry::assemble_transform(
@ -1781,18 +1756,16 @@ void Selection::render_synchronized_volumes() const
float color[3] = { 1.0f, 1.0f, 0.0f }; float color[3] = { 1.0f, 1.0f, 0.0f };
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
const GLVolume* volume = (*m_volumes)[i]; const GLVolume* volume = (*m_volumes)[i];
int object_idx = volume->object_idx(); int object_idx = volume->object_idx();
int volume_idx = volume->volume_idx(); int volume_idx = volume->volume_idx();
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
{
if (i == j) if (i == j)
continue; continue;
const GLVolume* v = (*m_volumes)[j]; const GLVolume* v = (*m_volumes)[j];
if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx)) if (v->object_idx() != object_idx || v->volume_idx() != volume_idx)
continue; continue;
render_bounding_box(v->transformed_convex_hull_bounding_box(), color); render_bounding_box(v->transformed_convex_hull_bounding_box(), color);
@ -1986,7 +1959,7 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
::glBegin(GL_QUADS); ::glBegin(GL_QUADS);
if ((camera_on_top && (type == 1)) || (!camera_on_top && (type == 2))) if ((camera_on_top && type == 1) || (!camera_on_top && type == 2))
::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f);
else else
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
@ -1997,7 +1970,7 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co
glsafe(::glEnd()); glsafe(::glEnd());
::glBegin(GL_QUADS); ::glBegin(GL_QUADS);
if ((camera_on_top && (type == 2)) || (!camera_on_top && (type == 1))) if ((camera_on_top && type == 2) || (!camera_on_top && type == 1))
::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f);
else else
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
@ -2014,9 +1987,9 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co
#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)
{ {
Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rot_xyz_from, rot_xyz_to)); const Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Vec3d axis = angle_axis.axis(); const Vec3d axis = angle_axis.axis();
double angle = angle_axis.angle(); const double angle = angle_axis.angle();
if (std::abs(angle) < 1e-8) if (std::abs(angle) < 1e-8)
return true; return true;
assert(std::abs(axis.x()) < 1e-8); assert(std::abs(axis.x()) < 1e-8);
@ -2053,24 +2026,22 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
std::set<unsigned int> done; // prevent processing volumes twice std::set<unsigned int> done; // prevent processing volumes twice
done.insert(m_list.begin(), m_list.end()); done.insert(m_list.begin(), m_list.end());
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
if (done.size() == m_volumes->size()) if (done.size() == m_volumes->size())
break; break;
const GLVolume* volume = (*m_volumes)[i]; const GLVolume* volume = (*m_volumes)[i];
int object_idx = volume->object_idx(); const int object_idx = volume->object_idx();
if (object_idx >= 1000) if (object_idx >= 1000)
continue; continue;
int instance_idx = volume->instance_idx(); const int instance_idx = volume->instance_idx();
const Vec3d& rotation = volume->get_instance_rotation(); const Vec3d& rotation = volume->get_instance_rotation();
const Vec3d& scaling_factor = volume->get_instance_scaling_factor(); const Vec3d& scaling_factor = volume->get_instance_scaling_factor();
const Vec3d& mirror = volume->get_instance_mirror(); const Vec3d& mirror = volume->get_instance_mirror();
// 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) {
{
if (done.size() == m_volumes->size()) if (done.size() == m_volumes->size())
break; break;
@ -2078,24 +2049,33 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
continue; continue;
GLVolume* v = (*m_volumes)[j]; GLVolume* v = (*m_volumes)[j];
if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx)) if (v->object_idx() != object_idx || v->instance_idx() == instance_idx)
continue; continue;
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()));
switch (sync_rotation_type) { switch (sync_rotation_type) {
case SYNC_ROTATION_NONE: case SYNC_ROTATION_NONE: {
#if ENABLE_ALLOW_NEGATIVE_Z
// 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()));
v->set_instance_offset(Z, volume->get_instance_offset().z());
break;
#else
// z only rotation -> keep instance z // z only rotation -> keep 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.
assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation())); assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation()));
break; break;
#endif // ENABLE_ALLOW_NEGATIVE_Z
}
case SYNC_ROTATION_FULL: case SYNC_ROTATION_FULL:
// rotation comes from place on face -> force given z // rotation comes from place on face -> force given z
v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2))); v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() });
break; break;
case SYNC_ROTATION_GENERAL: case SYNC_ROTATION_GENERAL:
// generic rotation -> update instance z with the delta of the rotation. // generic rotation -> update instance z with the delta of the rotation.
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());
v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff)); v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
break; break;
} }
@ -2113,27 +2093,25 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
void Selection::synchronize_unselected_volumes() void Selection::synchronize_unselected_volumes()
{ {
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
const GLVolume* volume = (*m_volumes)[i]; const GLVolume* volume = (*m_volumes)[i];
int object_idx = volume->object_idx(); const int object_idx = volume->object_idx();
if (object_idx >= 1000) if (object_idx >= 1000)
continue; continue;
int volume_idx = volume->volume_idx(); const int volume_idx = volume->volume_idx();
const Vec3d& offset = volume->get_volume_offset(); const Vec3d& offset = volume->get_volume_offset();
const Vec3d& rotation = volume->get_volume_rotation(); const Vec3d& rotation = volume->get_volume_rotation();
const Vec3d& scaling_factor = volume->get_volume_scaling_factor(); const Vec3d& scaling_factor = volume->get_volume_scaling_factor();
const Vec3d& mirror = volume->get_volume_mirror(); const Vec3d& mirror = volume->get_volume_mirror();
// Process unselected volumes. // Process unselected volumes.
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
{
if (j == i) if (j == i)
continue; continue;
GLVolume* v = (*m_volumes)[j]; GLVolume* v = (*m_volumes)[j];
if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx)) if (v->object_idx() != object_idx || v->volume_idx() != volume_idx)
continue; continue;
v->set_volume_offset(offset); v->set_volume_offset(offset);

View file

@ -129,7 +129,7 @@ private:
TransformCache m_instance; TransformCache m_instance;
public: public:
VolumeCache() {} VolumeCache() = default;
VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform); VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform);
const Vec3d& get_volume_position() const { return m_volume.position; } const Vec3d& get_volume_position() const { return m_volume.position; }