Tech ENABLE_TRANSFORMATIONS_BY_MATRICES - Scaling using object manipulator fields
Fixed conflicts during rebase with master
This commit is contained in:
parent
3b3edb5a97
commit
b76f9fc2ee
4 changed files with 159 additions and 43 deletions
|
@ -1585,8 +1585,8 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
|
|||
|
||||
if (from_galery) {
|
||||
#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.
|
||||
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
|
||||
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
||||
#else
|
||||
// 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.
|
||||
const GLVolume* v = selection.get_first_volume();
|
||||
#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.
|
||||
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
|
||||
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
||||
#else
|
||||
// Transform the new modifier to be aligned with the print bed.
|
||||
|
|
|
@ -1303,7 +1303,10 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
|||
transformation_type.set_instance();
|
||||
|
||||
#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
|
||||
if (!is_local_coordinates())
|
||||
transformation_type.set_relative();
|
||||
|
|
|
@ -713,6 +713,8 @@ const BoundingBoxf3& Selection::get_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()) {
|
||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_unscaled_instance_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
|
@ -736,6 +738,8 @@ const BoundingBoxf3& Selection::get_unscaled_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()) {
|
||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_scaled_instance_bounding_box);
|
||||
*bbox = BoundingBoxf3();
|
||||
|
@ -753,6 +757,65 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
|
|||
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()
|
||||
{
|
||||
if (!m_valid)
|
||||
|
@ -1350,54 +1413,66 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
|
|||
if (!m_valid)
|
||||
return;
|
||||
|
||||
Vec3d relative_scale = scale;
|
||||
|
||||
for (unsigned int i : m_list) {
|
||||
GLVolume& v = *(*m_volumes)[i];
|
||||
const VolumeCache& volume_data = m_cache.volumes_data[i];
|
||||
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()) {
|
||||
assert(transformation_type.joint());
|
||||
v.set_instance_transformation(Geometry::assemble_transform(inst_trafo.get_offset_matrix(), inst_trafo.get_rotation_matrix(),
|
||||
Geometry::scale_transform(scale), inst_trafo.get_mirror_matrix()));
|
||||
|
||||
if (transformation_type.absolute()) {
|
||||
// convert from absolute scaling to relative scaling
|
||||
BoundingBoxf3 original_box;
|
||||
if (m_mode == Instance) {
|
||||
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 {
|
||||
if (transformation_type.world()) {
|
||||
const Transform3d scale_matrix = Geometry::scale_transform(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(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;
|
||||
if (transformation_type.world())
|
||||
original_box = v.transformed_convex_hull_bounding_box((volume_data.get_instance_transform() *
|
||||
volume_data.get_volume_transform()).get_matrix_no_scaling_factor());
|
||||
else if (transformation_type.instance())
|
||||
original_box = v.transformed_convex_hull_bounding_box(volume_data.get_volume_transform().get_matrix_no_scaling_factor());
|
||||
else
|
||||
original_box = v.bounding_box();
|
||||
}
|
||||
|
||||
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
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
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()));
|
||||
// constrained scaling - add offset to keep constraint
|
||||
offset = translation;
|
||||
|
||||
v.set_instance_transformation(Geometry::translation_transform(offset) * inst_trafo.get_matrix() * scale_matrix);
|
||||
}
|
||||
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
|
||||
|
|
|
@ -225,10 +225,24 @@ private:
|
|||
Cache m_cache;
|
||||
Clipboard m_clipboard;
|
||||
std::optional<BoundingBoxf3> m_bounding_box;
|
||||
// Bounding box of a selection, with no instance scaling applied. This bounding box
|
||||
// is useful for absolute scaling of tilted objects in world coordinate space.
|
||||
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
|
||||
// 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;
|
||||
// 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;
|
||||
#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
|
||||
GLModel m_vbo_sphere;
|
||||
|
@ -355,10 +369,25 @@ public:
|
|||
|
||||
unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
|
||||
const BoundingBoxf3& get_bounding_box() const;
|
||||
// Bounding box of a selection, with no instance scaling applied. This bounding box
|
||||
// is useful for absolute scaling of tilted objects in world coordinate space.
|
||||
// Bounding box of a single full instance selection, in world coordinates, with no instance scaling applied.
|
||||
// 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;
|
||||
// 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;
|
||||
#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();
|
||||
|
||||
|
@ -429,7 +458,16 @@ private:
|
|||
void do_remove_volume(unsigned int volume_idx);
|
||||
void do_remove_instance(unsigned int object_idx, unsigned int instance_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(); }
|
||||
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
|
||||
void render_synchronized_volumes();
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
|
|
Loading…
Reference in a new issue