Selection of modifiers in 3D scene
This commit is contained in:
parent
de981ce8be
commit
57c769b63b
6 changed files with 133 additions and 11 deletions
|
@ -1038,6 +1038,9 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const
|
|||
|
||||
for (const ModelVolume* v : volumes)
|
||||
{
|
||||
if (!v->is_model_part())
|
||||
continue;
|
||||
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
Transform3d mv = mi * v->get_matrix();
|
||||
const TriangleMesh& hull = v->get_convex_hull();
|
||||
|
@ -1152,6 +1155,14 @@ void ModelVolume::set_material(t_model_material_id material_id, const ModelMater
|
|||
this->object->get_model()->add_material(material_id, material);
|
||||
}
|
||||
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
void ModelVolume::translate_geometry(const Vec3d& displacement)
|
||||
{
|
||||
mesh.translate((float)displacement(0), (float)displacement(1), (float)displacement(2));
|
||||
m_convex_hull.translate((float)displacement(0), (float)displacement(1), (float)displacement(2));
|
||||
}
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
|
||||
void ModelVolume::calculate_convex_hull()
|
||||
{
|
||||
m_convex_hull = mesh.convex_hull_3d();
|
||||
|
|
|
@ -322,6 +322,10 @@ public:
|
|||
void rotate(double angle, const Vec3d& axis);
|
||||
void mirror(Axis axis);
|
||||
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
void translate_geometry(const Vec3d& displacement);
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
|
||||
void calculate_convex_hull();
|
||||
const TriangleMesh& get_convex_hull() const;
|
||||
|
||||
|
|
|
@ -1197,16 +1197,30 @@ void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selectio
|
|||
if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx))
|
||||
return;
|
||||
|
||||
// resets the current list if needed
|
||||
const GLVolume* volume = (*m_volumes)[volume_idx];
|
||||
if (as_single_selection || volume->is_wipe_tower || is_wipe_tower() || volume->is_modifier || is_modifier())
|
||||
// wipe tower is already selected
|
||||
if (is_wipe_tower() && volume->is_wipe_tower)
|
||||
return;
|
||||
|
||||
// resets the current list if needed
|
||||
bool needs_reset = as_single_selection;
|
||||
needs_reset |= volume->is_wipe_tower;
|
||||
needs_reset |= is_wipe_tower() && !volume->is_wipe_tower;
|
||||
needs_reset |= !is_modifier() && volume->is_modifier;
|
||||
needs_reset |= is_modifier() && !volume->is_modifier;
|
||||
|
||||
if (needs_reset)
|
||||
clear();
|
||||
|
||||
m_mode = volume->is_modifier ? Volume : Instance;
|
||||
|
||||
switch (m_mode)
|
||||
{
|
||||
case Volume:
|
||||
{
|
||||
_add_volume(volume_idx);
|
||||
if (is_empty() || ((is_modifier() && volume->is_modifier) && (volume->instance_idx() == get_instance_idx())))
|
||||
_add_volume(volume_idx);
|
||||
|
||||
break;
|
||||
}
|
||||
case Instance:
|
||||
|
@ -1435,6 +1449,11 @@ void GLCanvas3D::Selection::translate(const Vec3d& displacement)
|
|||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Volume)
|
||||
_synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
m_bounding_box_dirty = true;
|
||||
}
|
||||
|
||||
|
@ -1466,7 +1485,6 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation)
|
|||
{
|
||||
// extracts rotations from the composed transformation
|
||||
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
||||
(*m_volumes)[i]->set_volume_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_volume_position() - m_cache.dragging_center));
|
||||
(*m_volumes)[i]->set_volume_rotation(new_rotation);
|
||||
}
|
||||
#else
|
||||
|
@ -1481,6 +1499,8 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation)
|
|||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Instance)
|
||||
_synchronize_unselected_instances();
|
||||
else if (m_mode == Volume)
|
||||
_synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
m_bounding_box_dirty = true;
|
||||
|
@ -1497,6 +1517,7 @@ void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal)
|
|||
|
||||
for (unsigned int i : m_list)
|
||||
{
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_volume_scale_matrix();
|
||||
Vec3d scaling_factor = Vec3d(1./wst(0,0), 1./wst(1,1), 1./wst(2,2));
|
||||
|
||||
|
@ -1512,6 +1533,23 @@ void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal)
|
|||
|
||||
Vec3d new_rotation = Geometry::extract_euler_angles(extra_rotation * m_cache.volumes_data[i].get_instance_rotation_matrix() );
|
||||
(*m_volumes)[i]->set_instance_rotation(new_rotation);
|
||||
#else
|
||||
Transform3d wst = m_cache.volumes_data[i].get_scale_matrix() * m_cache.volumes_data[i].get_scale_matrix();
|
||||
Vec3d scaling_factor = Vec3d(1. / wst(0, 0), 1. / wst(1, 1), 1. / wst(2, 2));
|
||||
|
||||
Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_rotation_matrix() * m_cache.volumes_data[i].get_rotation_matrix());
|
||||
Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor) * normal;
|
||||
transformed_normal.normalize();
|
||||
|
||||
Vec3d axis = transformed_normal(2) > 0.999f ? Vec3d(1., 0., 0.) : Vec3d(transformed_normal.cross(Vec3d(0., 0., -1.)));
|
||||
axis.normalize();
|
||||
|
||||
Transform3d extra_rotation = Transform3d::Identity();
|
||||
extra_rotation.rotate(Eigen::AngleAxisd(acos(-transformed_normal(2)), axis));
|
||||
|
||||
Vec3d new_rotation = Geometry::extract_euler_angles(extra_rotation * m_cache.volumes_data[i].get_rotation_matrix());
|
||||
(*m_volumes)[i]->set_rotation(new_rotation);
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
|
@ -1553,7 +1591,6 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale)
|
|||
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
|
||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
||||
(*m_volumes)[i]->set_volume_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_volume_position() - m_cache.dragging_center));
|
||||
(*m_volumes)[i]->set_volume_scaling_factor(new_scale);
|
||||
}
|
||||
#else
|
||||
|
@ -1569,6 +1606,8 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale)
|
|||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Instance)
|
||||
_synchronize_unselected_instances();
|
||||
else if (m_mode == Volume)
|
||||
_synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
m_bounding_box_dirty = true;
|
||||
|
@ -1592,6 +1631,8 @@ void GLCanvas3D::Selection::mirror(Axis axis)
|
|||
#if !DISABLE_INSTANCES_SYNCH
|
||||
if (m_mode == Instance)
|
||||
_synchronize_unselected_instances();
|
||||
else if (m_mode == Volume)
|
||||
_synchronize_unselected_volumes();
|
||||
#endif // !DISABLE_INSTANCES_SYNCH
|
||||
|
||||
m_bounding_box_dirty = true;
|
||||
|
@ -1746,7 +1787,7 @@ void GLCanvas3D::Selection::_update_type()
|
|||
if (first->is_wipe_tower)
|
||||
m_type = WipeTower;
|
||||
else if (first->is_modifier)
|
||||
m_type = Modifier;
|
||||
m_type = SingleModifier;
|
||||
else
|
||||
{
|
||||
const ModelObject* model_object = m_model->objects[first->object_idx()];
|
||||
|
@ -1769,6 +1810,8 @@ void GLCanvas3D::Selection::_update_type()
|
|||
m_type = SingleFullObject;
|
||||
else if ((m_cache.content.begin()->second.size() == 1) && (volumes_count == (unsigned int)m_list.size()))
|
||||
m_type = SingleFullInstance;
|
||||
else if ((*m_volumes)[*m_list.begin()]->is_modifier)
|
||||
m_type = MultipleModifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1790,9 +1833,14 @@ void GLCanvas3D::Selection::_update_type()
|
|||
std::cout << "selection type: WipeTower" << std::endl;
|
||||
break;
|
||||
}
|
||||
case Modifier:
|
||||
case SingleModifier:
|
||||
{
|
||||
std::cout << "selection type: Modifier" << std::endl;
|
||||
std::cout << "selection type: SingleModifier" << std::endl;
|
||||
break;
|
||||
}
|
||||
case MultipleModifier:
|
||||
{
|
||||
std::cout << "selection type: MultipleModifier" << std::endl;
|
||||
break;
|
||||
}
|
||||
case SingleFullObject:
|
||||
|
@ -2012,6 +2060,53 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances()
|
|||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::Selection::_synchronize_unselected_volumes()
|
||||
{
|
||||
for (unsigned int i : m_list)
|
||||
{
|
||||
const GLVolume* volume = (*m_volumes)[i];
|
||||
int object_idx = volume->object_idx();
|
||||
if (object_idx >= 1000)
|
||||
continue;
|
||||
|
||||
int volume_idx = volume->volume_idx();
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
const Vec3d& offset = volume->get_volume_offset();
|
||||
const Vec3d& rotation = volume->get_volume_rotation();
|
||||
const Vec3d& scaling_factor = volume->get_volume_scaling_factor();
|
||||
const Vec3d& mirror = volume->get_volume_mirror();
|
||||
#else
|
||||
const Vec3d& offset = volume->get_offset();
|
||||
const Vec3d& rotation = volume->get_rotation();
|
||||
const Vec3d& scaling_factor = volume->get_scaling_factor();
|
||||
const Vec3d& mirror = volume->get_mirror();
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
|
||||
// Process unselected volumes.
|
||||
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
|
||||
{
|
||||
if (j == i)
|
||||
continue;
|
||||
|
||||
GLVolume* v = (*m_volumes)[j];
|
||||
if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx))
|
||||
continue;
|
||||
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
v->set_volume_offset(offset);
|
||||
v->set_volume_rotation(rotation);
|
||||
v->set_volume_scaling_factor(scaling_factor);
|
||||
v->set_volume_mirror(mirror);
|
||||
#else
|
||||
v->set_offset(offset);
|
||||
v->set_rotation(Vec3d(rotation));
|
||||
v->set_scaling_factor(scaling_factor);
|
||||
v->set_mirror(mirror);
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float GLCanvas3D::Gizmos::OverlayTexturesScale = 0.75f;
|
||||
const float GLCanvas3D::Gizmos::OverlayOffsetX = 10.0f * OverlayTexturesScale;
|
||||
const float GLCanvas3D::Gizmos::OverlayGapY = 5.0f * OverlayTexturesScale;
|
||||
|
|
|
@ -373,7 +373,8 @@ public:
|
|||
Invalid,
|
||||
Empty,
|
||||
WipeTower,
|
||||
Modifier,
|
||||
SingleModifier,
|
||||
MultipleModifier,
|
||||
SingleFullObject,
|
||||
SingleFullInstance,
|
||||
Mixed
|
||||
|
@ -483,7 +484,7 @@ public:
|
|||
|
||||
bool is_empty() const { return m_type == Empty; }
|
||||
bool is_wipe_tower() const { return m_type == WipeTower; }
|
||||
bool is_modifier() const { return m_type == Modifier; }
|
||||
bool is_modifier() const { return (m_type == SingleModifier) || (m_type == MultipleModifier); }
|
||||
bool is_single_full_instance() const;
|
||||
bool is_single_full_object() const { return m_type == SingleFullObject; }
|
||||
bool is_mixed() const { return m_type == Mixed; }
|
||||
|
@ -533,6 +534,7 @@ public:
|
|||
void _render_selected_volumes() const;
|
||||
void _render_bounding_box(const BoundingBoxf3& box, float* color) const;
|
||||
void _synchronize_unselected_instances();
|
||||
void _synchronize_unselected_volumes();
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -734,19 +734,27 @@ void ObjectList::load_part( ModelObject* model_object,
|
|||
if (model_object->origin_translation != Vec3d::Zero())
|
||||
{
|
||||
object->center_around_origin();
|
||||
#if !ENABLE_MODELVOLUME_TRANSFORM
|
||||
object->ensure_on_bed();
|
||||
#endif // !ENABLE_MODELVOLUME_TRANSFORM
|
||||
delta = model_object->origin_translation - object->origin_translation;
|
||||
}
|
||||
for (auto volume : object->volumes) {
|
||||
#if ENABLE_MODELVOLUME_TRANSFORM
|
||||
Vec3d shift = volume->mesh.bounding_box().center();
|
||||
volume->translate_geometry(-shift);
|
||||
volume->translate(delta + shift);
|
||||
#endif // ENABLE_MODELVOLUME_TRANSFORM
|
||||
auto new_volume = model_object->add_volume(*volume);
|
||||
new_volume->set_type(static_cast<ModelVolume::Type>(type));
|
||||
boost::filesystem::path(input_file).filename().string();
|
||||
new_volume->name = boost::filesystem::path(input_file).filename().string();
|
||||
|
||||
part_names.Add(new_volume->name);
|
||||
|
||||
#if !ENABLE_MODELVOLUME_TRANSFORM
|
||||
if (delta != Vec3d::Zero())
|
||||
new_volume->translate(delta);
|
||||
#endif // !ENABLE_MODELVOLUME_TRANSFORM
|
||||
|
||||
// set a default extruder value, since user can't add it manually
|
||||
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||
|
|
|
@ -2255,7 +2255,9 @@ void Plater::changed_object(int obj_idx)
|
|||
if (list->is_parts_changed()) {
|
||||
// recenter and re - align to Z = 0
|
||||
auto model_object = p->model.objects[obj_idx];
|
||||
#if !ENABLE_MODELVOLUME_TRANSFORM
|
||||
model_object->center_around_origin();
|
||||
#endif // !ENABLE_MODELVOLUME_TRANSFORM
|
||||
model_object->ensure_on_bed();
|
||||
_3DScene::reload_scene(p->canvas3D, false);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue