mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-08-05 19:56:09 +08:00
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:
parent
bccb230fc1
commit
98cce3b656
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user