Tech ENABLE_ALLOW_NEGATIVE_Z-> Synchronize sinking instances
This commit is contained in:
parent
3f6123e653
commit
bb18edde0a
2 changed files with 79 additions and 101 deletions
|
@ -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);
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
Loading…
Reference in a new issue