NEW:add Object coordinates in move gizmo

jira: none
Part of the code references PrusaSlicer,thanks for PrusaSlicer and enricoturri1966
commit c12eeee12f9e2c91a9dfe7905f1370143805f038
Author: enricoturri1966 <enricoturri@seznam.cz>
Date:   Mon Oct 2 14:26:36 2023 +0200

    SPE-1926: Tech ENABLE_CGAL_BOUNDING_SPHERE - Use selection's bounding sphere center as pivot for rotations

Change-Id: Iae7e4539c198af3ff1aa99e1c0ce015fbcf80256
(cherry picked from commit 2b73bc915ee27218c9803ba0a01b0d3e47adf1da)
This commit is contained in:
zhou.xu 2024-04-03 14:21:43 +08:00 committed by Lane.Wei
parent bccb230fc1
commit 98cce3b656
7 changed files with 150 additions and 21 deletions

View File

@ -79,6 +79,7 @@ bool GLGizmoMove3D::on_is_activable() const
void GLGizmoMove3D::on_set_state() {
if (get_state() == On) {
m_object_manipulation->set_coordinates_type(ECoordinatesType::World);
m_object_manipulation->set_use_object_cs(false);
}
}
@ -87,7 +88,7 @@ void GLGizmoMove3D::on_start_dragging()
if (m_hover_id != -1) {
m_displacement = Vec3d::Zero();
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
m_starting_drag_position = m_grabbers[m_hover_id].center;
m_starting_drag_position = m_orient_matrix *m_grabbers[m_hover_id].center;
m_starting_box_center = box.center();
m_starting_box_bottom_center = box.center();
m_starting_box_bottom_center(2) = box.min(2);
@ -116,17 +117,19 @@ void GLGizmoMove3D::on_render()
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
const BoundingBoxf3& box = selection.get_bounding_box();
const Vec3d& center = box.center();
const auto &[box, box_trafo] = selection.get_bounding_box_in_current_reference_system();
m_bounding_box = box;
m_center = box_trafo.translation();
m_orient_matrix = box_trafo;
float space_size = 20.f *INV_ZOOM;
#if ENABLE_FIXED_GRABBER
// x axis
m_grabbers[0].center = { box.max.x() + space_size, center.y(), center.z() };
m_grabbers[0].center = {m_bounding_box.max.x() + space_size, 0, 0};
// y axis
m_grabbers[1].center = { center.x(), box.max.y() + space_size, center.z() };
m_grabbers[1].center = {0, m_bounding_box.max.y() + space_size,0};
// z axis
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + space_size };
m_grabbers[2].center = {0,0, m_bounding_box.max.z() + space_size};
for (int i = 0; i < 3; ++i) {
m_grabbers[i].color = AXES_COLOR[i];
@ -147,7 +150,8 @@ void GLGizmoMove3D::on_render()
#endif
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
glsafe(::glPushMatrix());
glsafe(::glMultMatrixd(Geometry::Transformation(m_orient_matrix).get_matrix().data()));
// draw grabbers
for (unsigned int i = 0; i < 3; ++i) {
if (m_grabbers[i].enabled) render_grabber_extension((Axis) i, box, false);
@ -161,20 +165,20 @@ void GLGizmoMove3D::on_render()
glLineStipple(1, 0x0FFF);
glEnable(GL_LINE_STIPPLE);
::glBegin(GL_LINES);
::glVertex3dv(center.data());
::glVertex3dv(origin.data());
// use extension center
::glVertex3dv(m_grabbers[i].center.data());
glsafe(::glEnd());
glDisable(GL_LINE_STIPPLE);
}
}
glsafe(::glPopMatrix());
}
void GLGizmoMove3D::on_render_for_picking()
{
glsafe(::glDisable(GL_DEPTH_TEST));
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
//BBS donot render base grabber for picking
//render_grabbers_for_picking(box);
@ -185,10 +189,12 @@ void GLGizmoMove3D::on_render_for_picking()
m_grabbers[i].color = color;
}
}
render_grabber_extension(X, box, true);
render_grabber_extension(Y, box, true);
render_grabber_extension(Z, box, true);
glsafe(::glPushMatrix());
glsafe(::glMultMatrixd(Geometry::Transformation(m_orient_matrix).get_matrix().data()));
render_grabber_extension(X, m_bounding_box, true);
render_grabber_extension(Y, m_bounding_box, true);
render_grabber_extension(Z, m_bounding_box, true);
glsafe(::glPopMatrix());
}
//BBS: add input window for move

View File

@ -16,7 +16,10 @@ class GLGizmoMove3D : public GLGizmoBase
static const double Offset;
Vec3d m_displacement;
Vec3d origin = Vec3d::Zero();
Vec3d m_center{Vec3d::Zero()};
BoundingBoxf3 m_bounding_box;
Transform3d m_orient_matrix{Transform3d::Identity()};
double m_snap_step;
Vec3d m_starting_drag_position;

View File

@ -976,7 +976,22 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
case Move:
{
// Apply new temporary offset
selection.translate(get_displacement());
TransformationType trafo_type;
trafo_type.set_relative();
switch (wxGetApp().obj_manipul()->get_coordinates_type()) {
case ECoordinatesType::Instance: {
trafo_type.set_instance();
break;
}
case ECoordinatesType::Local: {
trafo_type.set_local();
break;
}
default: {
break;
}
}
selection.translate(get_displacement(), trafo_type);
// BBS
//wxGetApp().obj_manipul()->set_dirty();
break;

View File

@ -94,6 +94,7 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.;
}
else {//if (is_local_coordinates()) {//for scale
m_new_position = Vec3d::Zero();
m_new_rotation = volume->get_instance_rotation() * (180. / M_PI);
m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
m_new_scale = volume->get_instance_scaling_factor() * 100.;
@ -478,8 +479,8 @@ void GizmoObjectManipulation::set_uniform_scaling(const bool use_uniform_scale)
void GizmoObjectManipulation::set_coordinates_type(ECoordinatesType type)
{
if (wxGetApp().get_mode() == comSimple)
type = ECoordinatesType::World;
/*if (wxGetApp().get_mode() == comSimple)
type = ECoordinatesType::World;*/
if (m_coordinates_type == type) return;
@ -543,7 +544,23 @@ bool GizmoObjectManipulation::reset_button(ImGuiWrapper *imgui_wrapper, float ca
return unit_size + 8.0;
}
void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit)
bool GizmoObjectManipulation::bbl_checkbox(const wxString &label, bool &value)
{
bool result;
bool b_value = value;
if (b_value) {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f));
}
auto label_utf8 = into_u8(label);
result = ImGui::BBLCheckbox(label_utf8.c_str(), &value);
if (b_value) { ImGui::PopStyleColor(3); }
return result;
}
void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit)
{
// BBS: GUI refactor: move gizmo to the right
if (abs(last_move_input_window_width) > 0.01f) {
@ -602,7 +619,12 @@ void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper,
ImGui::AlignTextToFramePadding();
unsigned int current_active_id = ImGui::GetActiveID();
ImGui::PushItemWidth(caption_max);
imgui_wrapper->text(_L("World coordinates"));
if (m_use_object_cs) {
imgui_wrapper->text(_L("Object coordinates"));
}
else {
imgui_wrapper->text(_L("World coordinates"));
}
ImGui::SameLine(caption_max + index * space_size);
ImGui::PushItemWidth(unit_size);
ImGui::TextAlignCenter("X");
@ -629,6 +651,17 @@ void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper,
ImGui::SameLine(caption_max + (++index_unit) * unit_size + (++index) * space_size);
imgui_wrapper->text(this->m_new_unit_string);
if (bbl_checkbox(_L("Object coordinates"), m_use_object_cs)) {
if (m_use_object_cs) {
set_coordinates_type(ECoordinatesType::Instance);
}
else {
set_coordinates_type(ECoordinatesType::World);
}
UpdateAndShow(true);
return;//avoid update(current_active_id, "position", original_position
}
for (int i = 0;i<display_position.size();i++)
{
if (display_position[i] > MAX_NUM)display_position[i] = MAX_NUM;

View File

@ -53,7 +53,7 @@ public:
Cache m_cache;
bool m_imperial_units { false };
bool m_use_object_cs{false};
// Mirroring buttons and their current state
//enum MirrorButtonState {
// mbHidden,
@ -106,6 +106,7 @@ public:
void set_uniform_scaling(const bool uniform_scale);
bool get_uniform_scaling() const { return m_uniform_scale; }
void set_use_object_cs(bool flag) { m_use_object_cs = flag; }
// Does the object manipulation panel work in World or Local coordinates?
void set_coordinates_type(ECoordinatesType type);
ECoordinatesType get_coordinates_type() const { return m_coordinates_type; }
@ -121,6 +122,7 @@ public:
void do_render_scale_input_window(ImGuiWrapper* imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
float max_unit_size(int number, Vec3d &vec1, Vec3d &vec2,std::string str);
bool reset_button(ImGuiWrapper *imgui_wrapper, float caption_max, float unit_size, float space_size, float end_text_size);
bool bbl_checkbox(const wxString &label, bool &value);
private:
void reset_settings_value();

View File

@ -1128,6 +1128,75 @@ void Selection::translate(const Vec3d &displacement, bool local)
}
}
void Selection::translate(const Vec3d &displacement, TransformationType transformation_type)
{
if (!m_valid) return;
for (unsigned int i : m_list) {
GLVolume & v = *(*m_volumes)[i];
const VolumeCache &volume_data = m_cache.volumes_data[i];
if (m_mode == Instance && !is_wipe_tower()) {
assert(is_from_fully_selected_instance(i));
if (transformation_type.instance()) {
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement);
} else
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
} else {
if (v.is_wipe_tower) {//in world cs
int plate_idx = v.object_idx() - 1000;
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->get_bounding_box();
Vec3d tower_size = v.bounding_box().size();
Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position();
Vec3d actual_displacement = displacement;
const double margin = WIPE_TOWER_MARGIN;
actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() *
m_cache.volumes_data[i].get_instance_mirror_matrix())
.inverse() *
displacement;
if (tower_origin(0) + actual_displacement(0) - margin < plate_bbox.min(0)) {
actual_displacement(0) = plate_bbox.min(0) - tower_origin(0) + margin;
} else if (tower_origin(0) + actual_displacement(0) + tower_size(0) + margin > plate_bbox.max(0)) {
actual_displacement(0) = plate_bbox.max(0) - tower_origin(0) - tower_size(0) - margin;
}
if (tower_origin(1) + actual_displacement(1) - margin < plate_bbox.min(1)) {
actual_displacement(1) = plate_bbox.min(1) - tower_origin(1) + margin;
} else if (tower_origin(1) + actual_displacement(1) + tower_size(1) + margin > plate_bbox.max(1)) {
actual_displacement(1) = plate_bbox.max(1) - tower_origin(1) - tower_size(1) - margin;
}
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + actual_displacement);
}
else if (transformation_type.local() && transformation_type.absolute()) {
const Geometry::Transformation &vol_trafo = volume_data.get_volume_transform();
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement);
} else {
Vec3d relative_disp = displacement;
if (transformation_type.world() && transformation_type.instance())
relative_disp = volume_data.get_instance_transform().get_scaling_factor_matrix().inverse() * relative_disp;
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(relative_disp), m_cache.dragging_center);
}
}
}
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
synchronize_unselected_instances(SYNC_ROTATION_NONE);
else if (m_mode == Volume)
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
ensure_not_below_bed();
}
set_bounding_boxes_dirty();
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
}
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
{

View File

@ -385,7 +385,8 @@ public:
const std::pair<Vec3d, double> get_bounding_sphere() const;
void setup_cache();
void translate(const Vec3d& displacement, bool local = false);
void translate(const Vec3d &displacement, bool local = false);//old
void translate(const Vec3d &displacement, TransformationType transformation_type);//new
void move_to_center(const Vec3d& displacement, bool local = false);
void rotate(const Vec3d& rotation, TransformationType transformation_type);
void flattening_rotate(const Vec3d& normal);