FIX:world cs is displayed incorrectly

The value of world coordinate system for model_volume
is displayed incorrectly

Jira: STUDIO-6399
code is from PrusaSlicer
thanks for PrusaSlicer and enricoturri1966
commit 325709c5ae9b937867b36103a41d12a102c99292
Author: enricoturri1966 <enricoturri@seznam.cz>
Date:   Thu Jan 26 15:49:00 2023 +0100

    SPE-1419 - Fixed reset skew resetting mirror, reset scale resetting mirror, changed labels in Object Manipulator panel, scale of instances using the Object Manipulator panel always made as absolute

Change-Id: I30fdd39effd73b8dc027e4263fa7e64937b84326
This commit is contained in:
enricoturri1966 2024-03-04 11:11:29 +08:00 committed by Lane.Wei
parent b52817301c
commit 0b46b9848b
4 changed files with 170 additions and 14 deletions

View File

@ -12,7 +12,7 @@
#include "libslic3r/Model.hpp"
#include "libslic3r/Geometry.hpp"
#include "slic3r/GUI/Selection.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/MainFrame.hpp"
@ -117,14 +117,34 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
m_new_title_string = L("Object Operations");
}
else if (selection.is_single_modifier() || selection.is_single_volume()) {
// the selection contains a single volume
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
m_new_position = volume->get_volume_offset();
m_new_rotation = volume->get_volume_rotation() * (180. / M_PI);
m_new_scale = volume->get_volume_scaling_factor() * 100.;
m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(volume->get_volume_transformation().get_scaling_factor().cwiseProduct(volume->bounding_box().size()));
const GLVolume *volume = selection.get_first_volume();
if (is_world_coordinates()) {
const Geometry::Transformation trafo(volume->world_matrix());
const Vec3d &offset = trafo.get_offset();
m_new_position = offset;
m_new_rotate_label_string = L("Rotate (relative)");
m_new_scale_label_string = L("Scale");
m_new_scale = Vec3d(100.0, 100.0, 100.0);
m_new_rotation = Vec3d::Zero();
m_new_size = selection.get_bounding_box_in_current_reference_system().first.size();
} else if (is_local_coordinates()) {
m_new_move_label_string = L("Translate (relative) [World]");
m_new_rotate_label_string = L("Rotate (relative)");
m_new_position = Vec3d::Zero();
m_new_rotation = Vec3d::Zero();
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
m_new_size = selection.get_bounding_box_in_current_reference_system().first.size();
} else {
m_new_position = volume->get_volume_offset();
m_new_rotate_label_string = L("Rotate (relative)");
m_new_rotation = Vec3d::Zero();
m_new_scale_label_string = L("Scale");
m_new_scale = Vec3d(100.0, 100.0, 100.0);
m_new_size = selection.get_bounding_box_in_current_reference_system().first.size();
}
m_new_enabled = true;
m_new_title_string = L("Volume Operations");
}
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
reset_settings_value();
@ -445,7 +465,7 @@ void GizmoObjectManipulation::reset_scale_value()
}
void GizmoObjectManipulation::set_uniform_scaling(const bool use_uniform_scale)
{
{
if (!use_uniform_scale)
// Recalculate cached values at this panel, refresh the screen.
this->UpdateAndShow(true);
@ -454,6 +474,24 @@ void GizmoObjectManipulation::set_uniform_scaling(const bool use_uniform_scale)
set_dirty();
}
void GizmoObjectManipulation::set_coordinates_type(ECoordinatesType type)
{
if (wxGetApp().get_mode() == comSimple)
type = ECoordinatesType::World;
if (m_coordinates_type == type) return;
m_coordinates_type = type;
m_world_coordinates = type == ECoordinatesType::World ? true : false;
//m_word_local_combo->SetSelection((int) m_coordinates_type);
this->UpdateAndShow(true);
GLCanvas3D *canvas = wxGetApp().plater()->canvas3D();
canvas->get_gizmos_manager().update_data();
canvas->set_as_dirty();
canvas->request_extra_frame();
}
static const char* label_values[2][3] = {
{ "##position_x", "##position_y", "##position_z"},
{ "##rotation_x", "##rotation_y", "##rotation_z"}

View File

@ -5,13 +5,12 @@
#include "libslic3r/Point.hpp"
#include <float.h>
#include "slic3r/GUI/Selection.hpp"
//#include "slic3r/GUI/GLCanvas3D.hpp"
namespace Slic3r {
namespace GUI {
class Selection;
class GLCanvas3D;
class GizmoObjectManipulation
@ -83,6 +82,7 @@ public:
bool m_uniform_scale {true};
// Does the object manipulation panel work in World or Local coordinates?
bool m_world_coordinates = true;
ECoordinatesType m_coordinates_type{ECoordinatesType::World};
bool m_show_clear_rotation { false };
bool m_show_clear_scale { false };
@ -108,8 +108,11 @@ public:
void set_uniform_scaling(const bool uniform_scale);
bool get_uniform_scaling() const { return m_uniform_scale; }
// Does the object manipulation panel work in World or Local coordinates?
void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); }
bool get_world_coordinates() const { return m_world_coordinates; }
void set_coordinates_type(ECoordinatesType type);
ECoordinatesType get_coordinates_type() const { return m_coordinates_type; }
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
void reset_cache() { m_cache.reset(); }

View File

@ -865,6 +865,101 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
return *m_scaled_instance_bounding_box;
}
const std::pair<BoundingBoxf3, Transform3d> &Selection::get_bounding_box_in_current_reference_system() const
{
static int last_coordinates_type = -1;
assert(!is_empty());
ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
if (m_mode == Instance && coordinates_type == ECoordinatesType::Local) coordinates_type = ECoordinatesType::World;
if (last_coordinates_type != int(coordinates_type)) const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system)->reset();
if (!m_bounding_box_in_current_reference_system.has_value()) {
last_coordinates_type = int(coordinates_type);
*const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system) = get_bounding_box_in_reference_system(coordinates_type);
}
return *m_bounding_box_in_current_reference_system;
}
std::pair<BoundingBoxf3, Transform3d> Selection::get_bounding_box_in_reference_system(ECoordinatesType type) const
{
//
// trafo to current reference system
//
Transform3d trafo;
switch (type) {
case ECoordinatesType::World: {
trafo = Transform3d::Identity();
break;
}
case ECoordinatesType::Instance: {
trafo = get_first_volume()->get_instance_transformation().get_matrix();
break;
}
case ECoordinatesType::Local: {
trafo = get_first_volume()->world_matrix();
break;
}
}
//
// trafo basis in world coordinates
//
Geometry::Transformation t(trafo);
t.reset_scaling_factor();
const Transform3d basis_trafo = t.get_matrix_no_offset();
std::vector<Vec3d> axes = {Vec3d::UnitX(), Vec3d::UnitY(), Vec3d::UnitZ()};
for (size_t i = 0; i < axes.size(); ++i) { axes[i] = basis_trafo * axes[i]; }
//
// calculate bounding box aligned to trafo basis
//
Vec3d min = {DBL_MAX, DBL_MAX, DBL_MAX};
Vec3d max = {-DBL_MAX, -DBL_MAX, -DBL_MAX};
for (unsigned int id : m_list) {
const GLVolume & vol = *get_volume(id);
const Transform3d vol_world_rafo = vol.world_matrix();
const TriangleMesh *mesh = vol.convex_hull();
if (mesh == nullptr) mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh();
assert(mesh != nullptr);
for (const stl_vertex &v : mesh->its.vertices) {
const Vec3d world_v = vol_world_rafo * v.cast<double>();
for (int i = 0; i < 3; ++i) {
const double i_comp = world_v.dot(axes[i]);
min(i) = std::min(min(i), i_comp);
max(i) = std::max(max(i), i_comp);
}
}
}
const Vec3d box_size = max - min;
Vec3d half_box_size = 0.5 * box_size;
Geometry::Transformation out_trafo(trafo);
Vec3d center = 0.5 * (min + max);
// Fix for non centered volume
// by move with calculated center(to volume center) and extend half box size
// e.g. for right aligned embossed text
if (m_list.size() == 1 && type == ECoordinatesType::Local) {
const GLVolume & vol = *get_volume(*m_list.begin());
const Transform3d vol_world_trafo = vol.world_matrix();
Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
for (size_t i = 0; i < 3; i++) {
// move center to local volume zero
center[i] = world_zero.dot(axes[i]);
// extend half size to bigger distance from center
half_box_size[i] = std::max(abs(center[i] - min[i]), abs(center[i] - max[i]));
}
}
const BoundingBoxf3 out_box(-half_box_size, half_box_size);
out_trafo.set_offset(basis_trafo * center);
return {out_box, out_trafo.get_matrix_no_scaling_factor()};
}
void Selection::start_dragging()
{
if (!m_valid)

View File

@ -26,6 +26,12 @@ using ModelObjectPtrs = std::vector<ModelObject*>;
namespace GUI {
enum ECoordinatesType : unsigned char {
World,
Instance,
Local
};
class TransformationType
{
public:
@ -214,6 +220,9 @@ private:
std::optional<BoundingBoxf3> m_unscaled_instance_bounding_box;
std::optional<BoundingBoxf3> m_scaled_instance_bounding_box;
// Bounding box aligned to the axis of the currently selected reference system (World/Object/Part)
// and transform to place and orient it in world coordinates
std::optional<std::pair<BoundingBoxf3, Transform3d>> m_bounding_box_in_current_reference_system;
#if ENABLE_RENDER_SELECTION_CENTER
GLModel m_vbo_sphere;
#endif // ENABLE_RENDER_SELECTION_CENTER
@ -330,6 +339,13 @@ public:
const BoundingBoxf3& get_unscaled_instance_bounding_box() const;
const BoundingBoxf3& get_scaled_instance_bounding_box() const;
// Returns the bounding box aligned to the axes of the currently selected reference system (World/Object/Part)
// and the transform to place and orient it in world coordinates
const std::pair<BoundingBoxf3, Transform3d> &get_bounding_box_in_current_reference_system() const;
// Returns the bounding box aligned to the axes of the given reference system
// and the transform to place and orient it in world coordinates
std::pair<BoundingBoxf3, Transform3d> get_bounding_box_in_reference_system(ECoordinatesType type) const;
void start_dragging();
void stop_dragging() { m_dragging = false; }
bool is_dragging() const { return m_dragging; }
@ -403,7 +419,11 @@ 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);
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();
m_bounding_box_in_current_reference_system.reset();
}
void render_selected_volumes() const;
void render_synchronized_volumes() const;
void render_bounding_box(const BoundingBoxf3& box, float* color) const;