Tech ENABLE_TRANSFORMATIONS_BY_MATRICES - Scaling using object manipulator fields

Fixed conflicts during rebase with master
This commit is contained in:
enricoturri1966 2022-05-19 10:01:54 +02:00
parent 3b3edb5a97
commit b76f9fc2ee
4 changed files with 159 additions and 43 deletions

View File

@ -1585,8 +1585,8 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
if (from_galery) { if (from_galery) {
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
// Transform the new modifier to be aligned with the print bed. // Transform the new modifier to be aligned with the print bed.
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box(); const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
#else #else
// Transform the new modifier to be aligned with the print bed. // Transform the new modifier to be aligned with the print bed.
@ -1662,8 +1662,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
// First (any) GLVolume of the selected instance. They all share the same instance matrix. // First (any) GLVolume of the selected instance. They all share the same instance matrix.
const GLVolume* v = selection.get_first_volume(); const GLVolume* v = selection.get_first_volume();
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
// Transform the new modifier to be aligned with the print bed. // Transform the new modifier to be aligned with the print bed.
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box(); const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
#else #else
// Transform the new modifier to be aligned with the print bed. // Transform the new modifier to be aligned with the print bed.

View File

@ -1303,7 +1303,10 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
transformation_type.set_instance(); transformation_type.set_instance();
#if ENABLE_TRANSFORMATIONS_BY_MATRICES #if ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale; if (!selection.is_single_full_instance() && !selection.is_single_volume_or_modifier())
transformation_type.set_relative();
const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
#else #else
if (!is_local_coordinates()) if (!is_local_coordinates())
transformation_type.set_relative(); transformation_type.set_relative();

View File

@ -713,6 +713,8 @@ const BoundingBoxf3& Selection::get_bounding_box() const
const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const
{ {
assert(is_single_full_instance());
if (!m_unscaled_instance_bounding_box.has_value()) { if (!m_unscaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_unscaled_instance_bounding_box); std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_unscaled_instance_bounding_box);
*bbox = BoundingBoxf3(); *bbox = BoundingBoxf3();
@ -736,6 +738,8 @@ const BoundingBoxf3& Selection::get_unscaled_instance_bounding_box() const
const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
{ {
assert(is_single_full_instance());
if (!m_scaled_instance_bounding_box.has_value()) { if (!m_scaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_scaled_instance_bounding_box); std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_scaled_instance_bounding_box);
*bbox = BoundingBoxf3(); *bbox = BoundingBoxf3();
@ -753,6 +757,65 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
return *m_scaled_instance_bounding_box; return *m_scaled_instance_bounding_box;
} }
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
const BoundingBoxf3& Selection::get_full_unscaled_instance_bounding_box() const
{
assert(is_single_full_instance());
if (!m_full_unscaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_unscaled_instance_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume& volume = *(*m_volumes)[i];
Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_full_unscaled_instance_bounding_box;
}
const BoundingBoxf3& Selection::get_full_scaled_instance_bounding_box() const
{
assert(is_single_full_instance());
if (!m_full_scaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_scaled_instance_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume& volume = *(*m_volumes)[i];
Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_full_scaled_instance_bounding_box;
}
const BoundingBoxf3& Selection::get_full_unscaled_instance_local_bounding_box() const
{
assert(is_single_full_instance());
if (!m_full_unscaled_instance_local_bounding_box.has_value()) {
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_unscaled_instance_local_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume& volume = *(*m_volumes)[i];
Transform3d trafo = volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_full_unscaled_instance_local_bounding_box;
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void Selection::setup_cache() void Selection::setup_cache()
{ {
if (!m_valid) if (!m_valid)
@ -1350,54 +1413,66 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
if (!m_valid) if (!m_valid)
return; return;
Vec3d relative_scale = scale;
for (unsigned int i : m_list) { for (unsigned int i : m_list) {
GLVolume& v = *(*m_volumes)[i]; GLVolume& v = *(*m_volumes)[i];
const VolumeCache& volume_data = m_cache.volumes_data[i]; const VolumeCache& volume_data = m_cache.volumes_data[i];
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform(); const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
if (m_mode == Instance) {
assert(is_from_fully_selected_instance(i)); if (transformation_type.absolute()) {
if (transformation_type.absolute()) { // convert from absolute scaling to relative scaling
assert(transformation_type.joint()); BoundingBoxf3 original_box;
v.set_instance_transformation(Geometry::assemble_transform(inst_trafo.get_offset_matrix(), inst_trafo.get_rotation_matrix(), if (m_mode == Instance) {
Geometry::scale_transform(scale), inst_trafo.get_mirror_matrix())); assert(is_from_fully_selected_instance(i));
if (transformation_type.world())
original_box = get_full_unscaled_instance_bounding_box();
else
original_box = get_full_unscaled_instance_local_bounding_box();
} }
else { else {
if (transformation_type.world()) { if (transformation_type.world())
const Transform3d scale_matrix = Geometry::scale_transform(scale); original_box = v.transformed_convex_hull_bounding_box((volume_data.get_instance_transform() *
const Transform3d offset_matrix = (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) ? volume_data.get_volume_transform()).get_matrix_no_scaling_factor());
// non-constrained scaling - add offset to scale around selection center else if (transformation_type.instance())
Geometry::translation_transform(m_cache.dragging_center + scale_matrix * (inst_trafo.get_offset() - m_cache.dragging_center)) : original_box = v.transformed_convex_hull_bounding_box(volume_data.get_volume_transform().get_matrix_no_scaling_factor());
// constrained scaling - add offset to keep constraint else
Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix(); original_box = v.bounding_box();
v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset()); }
}
else if (transformation_type.local()) {
const Transform3d scale_matrix = Geometry::scale_transform(scale);
Vec3d offset;
if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) {
// non-constrained scaling - add offset to scale around selection center
offset = inst_trafo.get_matrix_no_offset().inverse() * (inst_trafo.get_offset() - m_cache.dragging_center);
offset = inst_trafo.get_matrix_no_offset() * (scale_matrix * offset - offset);
}
else
// constrained scaling - add offset to keep constraint
offset = translation;
v.set_instance_transformation(Geometry::translation_transform(offset) * inst_trafo.get_matrix() * scale_matrix); relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(m_box.get_bounding_box().size());
}
if (m_mode == Instance) {
assert(is_from_fully_selected_instance(i));
if (transformation_type.world()) {
const Transform3d scale_matrix = Geometry::scale_transform(relative_scale);
const Transform3d offset_matrix = (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) ?
// non-constrained scaling - add offset to scale around selection center
Geometry::translation_transform(m_cache.dragging_center + scale_matrix * (inst_trafo.get_offset() - m_cache.dragging_center)) :
// constrained scaling - add offset to keep constraint
Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix();
v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset());
}
else if (transformation_type.local()) {
const Transform3d scale_matrix = Geometry::scale_transform(relative_scale);
Vec3d offset;
if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) {
// non-constrained scaling - add offset to scale around selection center
offset = inst_trafo.get_matrix_no_offset().inverse() * (inst_trafo.get_offset() - m_cache.dragging_center);
offset = inst_trafo.get_matrix_no_offset() * (scale_matrix * offset - offset);
} }
else else
assert(false); // constrained scaling - add offset to keep constraint
} offset = translation;
}
else { v.set_instance_transformation(Geometry::translation_transform(offset) * inst_trafo.get_matrix() * scale_matrix);
if (transformation_type.absolute()) {
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
v.set_volume_transformation(Geometry::assemble_transform(volume_trafo.get_offset_matrix(), volume_trafo.get_rotation_matrix(),
Geometry::scale_transform(scale), volume_trafo.get_mirror_matrix()));
} }
else else
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale)); assert(false);
} }
else
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale));
} }
#if !DISABLE_INSTANCES_SYNCH #if !DISABLE_INSTANCES_SYNCH

View File

@ -225,10 +225,24 @@ private:
Cache m_cache; Cache m_cache;
Clipboard m_clipboard; Clipboard m_clipboard;
std::optional<BoundingBoxf3> m_bounding_box; std::optional<BoundingBoxf3> m_bounding_box;
// Bounding box of a selection, with no instance scaling applied. This bounding box // Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
// is useful for absolute scaling of tilted objects in world coordinate space. // This bounding box is useful for absolute scaling of tilted objects in world coordinate space.
// Modifiers are NOT taken in account
std::optional<BoundingBoxf3> m_unscaled_instance_bounding_box; std::optional<BoundingBoxf3> m_unscaled_instance_bounding_box;
// Bounding box of a single full instance selection, in world coordinates.
// Modifiers are NOT taken in account
std::optional<BoundingBoxf3> m_scaled_instance_bounding_box; std::optional<BoundingBoxf3> m_scaled_instance_bounding_box;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
// Modifiers are taken in account
std::optional<BoundingBoxf3> m_full_unscaled_instance_bounding_box;
// Bounding box of a single full instance selection, in world coordinates.
// Modifiers are taken in account
std::optional<BoundingBoxf3> m_full_scaled_instance_bounding_box;
// Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied.
// Modifiers are taken in account
std::optional<BoundingBoxf3> m_full_unscaled_instance_local_bounding_box;
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
#if ENABLE_RENDER_SELECTION_CENTER #if ENABLE_RENDER_SELECTION_CENTER
GLModel m_vbo_sphere; GLModel m_vbo_sphere;
@ -355,10 +369,25 @@ public:
unsigned int volumes_count() const { return (unsigned int)m_list.size(); } unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
const BoundingBoxf3& get_bounding_box() const; const BoundingBoxf3& get_bounding_box() const;
// Bounding box of a selection, with no instance scaling applied. This bounding box // Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
// is useful for absolute scaling of tilted objects in world coordinate space. // This bounding box is useful for absolute scaling of tilted objects in world coordinate space.
// Modifiers are NOT taken in account
const BoundingBoxf3& get_unscaled_instance_bounding_box() const; const BoundingBoxf3& get_unscaled_instance_bounding_box() const;
// Bounding box of a single full instance selection, in world coordinates.
// Modifiers are NOT taken in account
const BoundingBoxf3& get_scaled_instance_bounding_box() const; const BoundingBoxf3& get_scaled_instance_bounding_box() const;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
// Modifiers are taken in account
const BoundingBoxf3& get_full_unscaled_instance_bounding_box() const;
// Bounding box of a single full instance selection, in world coordinates.
// Modifiers are taken in account
const BoundingBoxf3& get_full_scaled_instance_bounding_box() const;
// Bounding box of a single full instance selection, in local coordinates, with no instance scaling applied.
// Modifiers are taken in account
const BoundingBoxf3& get_full_unscaled_instance_local_bounding_box() const;
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void setup_cache(); void setup_cache();
@ -429,7 +458,16 @@ private:
void do_remove_volume(unsigned int volume_idx); void do_remove_volume(unsigned int volume_idx);
void do_remove_instance(unsigned int object_idx, unsigned int instance_idx); void do_remove_instance(unsigned int object_idx, unsigned int instance_idx);
void do_remove_object(unsigned int object_idx); void do_remove_object(unsigned int object_idx);
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void set_bounding_boxes_dirty() {
m_bounding_box.reset();
m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset();
m_full_unscaled_instance_bounding_box.reset(); m_full_scaled_instance_bounding_box.reset();
m_full_unscaled_instance_local_bounding_box.reset();;
}
#else
void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); } void set_bounding_boxes_dirty() { m_bounding_box.reset(); m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset(); }
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void render_synchronized_volumes(); void render_synchronized_volumes();
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE