Tech ENABLE_ALLOW_NEGATIVE_Z -> Keep sinking instances as sinking after applying scale gizmo

This commit is contained in:
enricoturri1966 2021-04-23 09:11:55 +02:00
parent d4695827ce
commit b600540411
2 changed files with 59 additions and 52 deletions

View file

@ -3660,10 +3660,13 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
for (const std::pair<int, int>& i : done) { for (const std::pair<int, int>& i : done) {
ModelObject* m = m_model->objects[i.first]; ModelObject* m = m_model->objects[i.first];
#if ENABLE_ALLOW_NEGATIVE_Z #if ENABLE_ALLOW_NEGATIVE_Z
double shift_z = m->get_instance_min_z(i.second);
// leave sinking instances as sinking // leave sinking instances as sinking
if (min_zs.empty() || min_zs.find({i.first, i.second})->second >= 0.0) { if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= 0.0 || shift_z > 0.0) {
#endif // ENABLE_ALLOW_NEGATIVE_Z Vec3d shift(0.0, 0.0, -shift_z);
#else
Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second)); Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second));
#endif // ENABLE_ALLOW_NEGATIVE_Z
m_selection.translate(i.first, i.second, shift); m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift); m->translate_instance(i.second, shift);
#if ENABLE_ALLOW_NEGATIVE_Z #if ENABLE_ALLOW_NEGATIVE_Z
@ -3685,14 +3688,26 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
if (!snapshot_type.empty()) if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(snapshot_type)); wxGetApp().plater()->take_snapshot(_(snapshot_type));
#if ENABLE_ALLOW_NEGATIVE_Z
// stores current min_z of instances
std::map<std::pair<int, int>, double> min_zs;
if (!snapshot_type.empty()) {
for (int i = 0; i < static_cast<int>(m_model->objects.size()); ++i) {
const ModelObject* obj = m_model->objects[i];
for (int j = 0; j < static_cast<int>(obj->instances.size()); ++j) {
min_zs[{ i, j }] = obj->instance_bounding_box(j).min(2);
}
}
}
#endif // ENABLE_ALLOW_NEGATIVE_Z
std::set<std::pair<int, int>> done; // keeps track of modified instances std::set<std::pair<int, int>> done; // keeps track of modified instances
Selection::EMode selection_mode = m_selection.get_mode(); Selection::EMode selection_mode = m_selection.get_mode();
for (const GLVolume* v : m_volumes.volumes) for (const GLVolume* v : m_volumes.volumes) {
{
int object_idx = v->object_idx(); int object_idx = v->object_idx();
if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx)) if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
continue; continue;
int instance_idx = v->instance_idx(); int instance_idx = v->instance_idx();
@ -3702,15 +3717,12 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
// Rotate instances/volumes // Rotate instances/volumes
ModelObject* model_object = m_model->objects[object_idx]; ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) if (model_object != nullptr) {
{ if (selection_mode == Selection::Instance) {
if (selection_mode == Selection::Instance)
{
model_object->instances[instance_idx]->set_scaling_factor(v->get_instance_scaling_factor()); model_object->instances[instance_idx]->set_scaling_factor(v->get_instance_scaling_factor());
model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
} }
else if (selection_mode == Selection::Volume) else if (selection_mode == Selection::Volume) {
{
model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor()); model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor());
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset()); model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
@ -3720,16 +3732,25 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
} }
// Fixes sinking/flying instances // Fixes sinking/flying instances
for (const std::pair<int, int>& i : done) for (const std::pair<int, int>& i : done) {
{
ModelObject* m = m_model->objects[i.first]; ModelObject* m = m_model->objects[i.first];
#if ENABLE_ALLOW_NEGATIVE_Z
double shift_z = m->get_instance_min_z(i.second);
// leave sinking instances as sinking
if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= 0.0 || shift_z > 0.0) {
Vec3d shift(0.0, 0.0, -shift_z);
#else
Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second)); Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second));
#endif // ENABLE_ALLOW_NEGATIVE_Z
m_selection.translate(i.first, i.second, shift); m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift); m->translate_instance(i.second, shift);
#if ENABLE_ALLOW_NEGATIVE_Z
}
#endif // ENABLE_ALLOW_NEGATIVE_Z
} }
if (!done.empty()) if (!done.empty())
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED)); post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_SCALED));
m_dirty = true; m_dirty = true;
} }

View file

@ -866,12 +866,10 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
if (!m_valid) if (!m_valid)
return; return;
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()) {
if (transformation_type.relative()) if (transformation_type.relative()) {
{
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale); Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3); Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
// extracts scaling factors from the composed transformation // extracts scaling factors from the composed transformation
@ -881,8 +879,7 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
volume.set_instance_scaling_factor(new_scale); volume.set_instance_scaling_factor(new_scale);
} }
else else {
{
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) { if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
// Non-uniform scaling. Transform the scaling factors into the local coordinate system. // Non-uniform scaling. Transform the scaling factors into the local coordinate system.
// This is only possible, if the instance rotation is mulitples of ninety degrees. // This is only possible, if the instance rotation is mulitples of ninety degrees.
@ -895,11 +892,9 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
} }
else if (is_single_volume() || is_single_modifier()) else if (is_single_volume() || is_single_modifier())
volume.set_volume_scaling_factor(scale); volume.set_volume_scaling_factor(scale);
else else {
{
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale); Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
if (m_mode == Instance) if (m_mode == Instance) {
{
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3); Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
// extracts scaling factors from the composed transformation // extracts scaling factors from the composed transformation
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
@ -908,13 +903,11 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
volume.set_instance_scaling_factor(new_scale); volume.set_instance_scaling_factor(new_scale);
} }
else if (m_mode == Volume) else if (m_mode == Volume) {
{
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3); Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
// extracts scaling factors from the composed transformation // extracts scaling factors from the composed transformation
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
if (transformation_type.joint()) if (transformation_type.joint()) {
{
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center); Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
volume.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); volume.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
} }
@ -930,34 +923,34 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
synchronize_unselected_volumes(); synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH #endif // !DISABLE_INSTANCES_SYNCH
#if !ENABLE_ALLOW_NEGATIVE_Z
ensure_on_bed(); ensure_on_bed();
#endif // !ENABLE_ALLOW_NEGATIVE_Z
this->set_bounding_boxes_dirty(); this->set_bounding_boxes_dirty();
} }
void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config) void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
{ {
if (is_empty() || (m_mode == Volume)) if (is_empty() || m_mode == Volume)
return; return;
// adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings // adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings
Vec3d box_size = get_bounding_box().size() + 0.01 * Vec3d::Ones(); Vec3d box_size = get_bounding_box().size() + 0.01 * Vec3d::Ones();
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config.option("bed_shape")); const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config.option("bed_shape"));
if (opt != nullptr) if (opt != nullptr) {
{
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
BoundingBoxf3 print_volume(Vec3d(unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0), Vec3d(unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config.opt_float("max_print_height"))); BoundingBoxf3 print_volume({ unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0 }, { unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config.opt_float("max_print_height") });
Vec3d print_volume_size = print_volume.size(); Vec3d print_volume_size = print_volume.size();
double sx = (box_size(0) != 0.0) ? print_volume_size(0) / box_size(0) : 0.0; double sx = (box_size(0) != 0.0) ? print_volume_size(0) / box_size(0) : 0.0;
double sy = (box_size(1) != 0.0) ? print_volume_size(1) / box_size(1) : 0.0; double sy = (box_size(1) != 0.0) ? print_volume_size(1) / box_size(1) : 0.0;
double sz = (box_size(2) != 0.0) ? print_volume_size(2) / box_size(2) : 0.0; double sz = (box_size(2) != 0.0) ? print_volume_size(2) / box_size(2) : 0.0;
if ((sx != 0.0) && (sy != 0.0) && (sz != 0.0)) if (sx != 0.0 && sy != 0.0 && sz != 0.0)
{ {
double s = std::min(sx, std::min(sy, sz)); double s = std::min(sx, std::min(sy, sz));
if (s != 1.0) if (s != 1.0) {
{ wxGetApp().plater()->take_snapshot(_L("Scale To Fit"));
wxGetApp().plater()->take_snapshot(_(L("Scale To Fit")));
TransformationType type; TransformationType type;
type.set_world(); type.set_world();
@ -987,8 +980,7 @@ void Selection::mirror(Axis axis)
bool single_full_instance = is_single_full_instance(); bool single_full_instance = is_single_full_instance();
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
if (single_full_instance) if (single_full_instance)
(*m_volumes)[i]->set_instance_mirror(axis, -(*m_volumes)[i]->get_instance_mirror(axis)); (*m_volumes)[i]->set_instance_mirror(axis, -(*m_volumes)[i]->get_instance_mirror(axis));
else if (m_mode == Volume) else if (m_mode == Volume)
@ -1010,8 +1002,7 @@ void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
if (!m_valid) if (!m_valid)
return; return;
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
GLVolume* v = (*m_volumes)[i]; GLVolume* v = (*m_volumes)[i];
if (v->object_idx() == (int)object_idx) if (v->object_idx() == (int)object_idx)
v->set_instance_offset(v->get_instance_offset() + displacement); v->set_instance_offset(v->get_instance_offset() + displacement);
@ -1020,8 +1011,7 @@ void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
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;
@ -1030,8 +1020,7 @@ void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
continue; continue;
// Process unselected volumes of the object. // Process unselected volumes of the object.
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;
@ -1055,18 +1044,16 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
if (!m_valid) if (!m_valid)
return; return;
for (unsigned int i : m_list) for (unsigned int i : m_list) {
{
GLVolume* v = (*m_volumes)[i]; GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() == (int)object_idx) && (v->instance_idx() == (int)instance_idx)) if (v->object_idx() == (int)object_idx && v->instance_idx() == (int)instance_idx)
v->set_instance_offset(v->get_instance_offset() + displacement); v->set_instance_offset(v->get_instance_offset() + displacement);
} }
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;
@ -1075,8 +1062,7 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
continue; continue;
// Process unselected volumes of the object. // Process unselected volumes of the object.
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;
@ -1084,7 +1070,7 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
continue; continue;
GLVolume* v = (*m_volumes)[j]; GLVolume* v = (*m_volumes)[j];
if ((v->object_idx() != object_idx) || (v->instance_idx() != (int)instance_idx)) if (v->object_idx() != object_idx || v->instance_idx() != (int)instance_idx)
continue; continue;
v->set_instance_offset(v->get_instance_offset() + displacement); v->set_instance_offset(v->get_instance_offset() + displacement);