Tech ENABLE_WORLD_COORDINATE - Fixed size of Rotate Gizmo in 3D scene
This commit is contained in:
parent
ec6daeb1d3
commit
2c02db3514
@ -884,7 +884,10 @@ void ObjectManipulation::update_if_dirty()
|
||||
m_lock_bnt->SetLock(m_uniform_scale);
|
||||
m_lock_bnt->SetToolTip(wxEmptyString);
|
||||
m_lock_bnt->enable();
|
||||
#if !ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (m_word_local_combo->GetSelection() != (int)m_coordinates_type)
|
||||
m_word_local_combo->SetSelection((int)m_coordinates_type);
|
||||
#else
|
||||
}
|
||||
|
||||
{
|
||||
@ -892,7 +895,7 @@ void ObjectManipulation::update_if_dirty()
|
||||
if (m_word_local_combo->GetSelection() != new_selection)
|
||||
m_word_local_combo->SetSelection(new_selection);
|
||||
}
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
if (m_new_enabled)
|
||||
m_og->enable();
|
||||
|
@ -129,7 +129,7 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
||||
, m_update_job_cancel(nullptr)
|
||||
{
|
||||
m_rotate_gizmo.set_group_id(0);
|
||||
m_rotate_gizmo.set_using_local_coordinate(true);
|
||||
m_rotate_gizmo.set_force_local_coordinate(true);
|
||||
// TODO: add suggestion to use https://fontawesome.com/
|
||||
// (copy & paste) unicode symbols from web
|
||||
// paste HEX unicode into notepad move cursor after unicode press [alt] + [x]
|
||||
|
@ -234,50 +234,17 @@ void GLGizmoRotate::on_render()
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void GLGizmoRotate::init_data_from_selection(const Selection& selection)
|
||||
{
|
||||
ECoordinatesType coordinates_type;
|
||||
if (m_using_local_coordinate ||
|
||||
selection.is_wipe_tower())
|
||||
coordinates_type = ECoordinatesType::Local;
|
||||
else
|
||||
coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||
if (coordinates_type == ECoordinatesType::World) {
|
||||
m_bounding_box = selection.get_bounding_box();
|
||||
m_center = m_bounding_box.center();
|
||||
}
|
||||
else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) {
|
||||
const GLVolume& v = *selection.get_first_volume();
|
||||
m_bounding_box = v.transformed_convex_hull_bounding_box(
|
||||
v.get_instance_transformation().get_scaling_factor_matrix() * v.get_volume_transformation().get_scaling_factor_matrix());
|
||||
m_center = v.world_matrix() * m_bounding_box.center();
|
||||
}
|
||||
else {
|
||||
m_bounding_box.reset();
|
||||
const Selection::IndicesList& ids = selection.get_volume_idxs();
|
||||
for (unsigned int id : ids) {
|
||||
const GLVolume& v = *selection.get_volume(id);
|
||||
m_bounding_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
|
||||
}
|
||||
const Geometry::Transformation inst_trafo = selection.get_first_volume()->get_instance_transformation();
|
||||
m_bounding_box = m_bounding_box.transformed(inst_trafo.get_scaling_factor_matrix());
|
||||
m_center = inst_trafo.get_matrix_no_scaling_factor() * m_bounding_box.center();
|
||||
}
|
||||
const auto [box, box_trafo] = m_force_local_coordinate ?
|
||||
selection.get_bounding_box_in_reference_system(ECoordinatesType::Local) : selection.get_bounding_box_in_current_reference_system();
|
||||
m_bounding_box = box;
|
||||
m_center = box_trafo.translation();
|
||||
m_orient_matrix = box_trafo;
|
||||
|
||||
m_radius = Offset + m_bounding_box.radius();
|
||||
m_snap_coarse_in_radius = m_radius / 3.0f;
|
||||
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
|
||||
m_snap_fine_in_radius = m_radius;
|
||||
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
|
||||
|
||||
if (coordinates_type == ECoordinatesType::World)
|
||||
m_orient_matrix = Transform3d::Identity();
|
||||
else if (coordinates_type == ECoordinatesType::Local && (selection.is_wipe_tower() || selection.is_single_volume_or_modifier())) {
|
||||
const GLVolume& v = *selection.get_first_volume();
|
||||
m_orient_matrix = v.get_instance_transformation().get_rotation_matrix() * v.get_volume_transformation().get_rotation_matrix();
|
||||
}
|
||||
else {
|
||||
const GLVolume& v = *selection.get_first_volume();
|
||||
m_orient_matrix = v.get_instance_transformation().get_rotation_matrix();
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
@ -531,7 +498,7 @@ Transform3d GLGizmoRotate::local_transform(const Selection& selection) const
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
return Geometry::translation_transform(m_center) * m_orient_matrix * ret;
|
||||
return m_orient_matrix * ret;
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
||||
ret = selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true) * ret;
|
||||
@ -546,7 +513,7 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray) cons
|
||||
Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
{
|
||||
double half_pi = 0.5 * double(PI);
|
||||
const double half_pi = 0.5 * double(PI);
|
||||
|
||||
Transform3d m = Transform3d::Identity();
|
||||
|
||||
@ -573,7 +540,7 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m = m * m_orient_matrix.inverse();
|
||||
m = m * Geometry::Transformation(m_orient_matrix).get_matrix_no_offset().inverse();
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
|
||||
m = m * selection.get_first_volume()->get_instance_transformation().get_matrix(true, false, true, true).inverse();
|
||||
|
@ -56,7 +56,7 @@ private:
|
||||
float m_old_angle{ 0.0f };
|
||||
|
||||
// emboss need to draw rotation gizmo in local coordinate systems
|
||||
bool m_using_local_coordinate{false};
|
||||
bool m_force_local_coordinate{ false };
|
||||
|
||||
ColorRGBA m_drag_color;
|
||||
ColorRGBA m_highlight_color;
|
||||
@ -71,7 +71,7 @@ public:
|
||||
std::string get_tooltip() const override;
|
||||
|
||||
void set_group_id(int group_id) { m_group_id = group_id; }
|
||||
void set_using_local_coordinate(bool use) { m_using_local_coordinate =use;}
|
||||
void set_force_local_coordinate(bool use) { m_force_local_coordinate = use; }
|
||||
|
||||
void start_dragging();
|
||||
void stop_dragging();
|
||||
|
@ -817,113 +817,117 @@ const std::pair<BoundingBoxf3, Transform3d>& Selection::get_bounding_box_in_curr
|
||||
|
||||
if (!m_bounding_box_in_current_reference_system.has_value()) {
|
||||
last_coordinates_type = int(coordinates_type);
|
||||
|
||||
BoundingBoxf3 original_box;
|
||||
Transform3d trafo;
|
||||
|
||||
//
|
||||
// calculate box aligned to current reference system
|
||||
//
|
||||
switch (coordinates_type)
|
||||
{
|
||||
case ECoordinatesType::World:
|
||||
{
|
||||
original_box = get_bounding_box();
|
||||
trafo = Transform3d::Identity();
|
||||
break;
|
||||
}
|
||||
case ECoordinatesType::Instance: {
|
||||
for (unsigned int id : m_list) {
|
||||
const GLVolume& v = *get_volume(id);
|
||||
original_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
|
||||
}
|
||||
trafo = get_first_volume()->get_instance_transformation().get_matrix();
|
||||
break;
|
||||
}
|
||||
case ECoordinatesType::Local: {
|
||||
assert(is_single_volume_or_modifier());
|
||||
const GLVolume& v = *get_first_volume();
|
||||
original_box = v.bounding_box();
|
||||
trafo = v.world_matrix();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// calculate box size in world coordinates
|
||||
//
|
||||
auto point_to_Vec4d = [](const Vec3d& p) { return Vec4d(p.x(), p.y(), p.z(), 1.0); };
|
||||
auto Vec4d_to_Vec3d = [](const Vec4d& v) { return Vec3d(v.x(), v.y(), v.z()); };
|
||||
|
||||
auto apply_transform = [](const std::vector<Vec4d>& original, const Transform3d& trafo, bool normalize) {
|
||||
std::vector<Vec4d> transformed(original.size());
|
||||
for (size_t i = 0; i < original.size(); ++i) {
|
||||
transformed[i] = trafo * original[i];
|
||||
if (normalize)
|
||||
transformed[i].normalize();
|
||||
}
|
||||
return transformed;
|
||||
};
|
||||
|
||||
auto calc_box_size = [point_to_Vec4d, Vec4d_to_Vec3d, apply_transform](const BoundingBoxf3& box, const Transform3d& trafo) {
|
||||
Geometry::Transformation transformation(trafo);
|
||||
|
||||
// box aligned to current reference system
|
||||
std::vector<Vec4d> homo_vertices = {
|
||||
point_to_Vec4d({ box.min.x(), box.min.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.min.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.max.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.min.x(), box.max.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.min.x(), box.min.y(), box.max.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.min.y(), box.max.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.max.y(), box.max.z() }),
|
||||
point_to_Vec4d({ box.min.x(), box.max.y(), box.max.z() })
|
||||
};
|
||||
|
||||
// box vertices in world coordinates
|
||||
std::vector<Vec4d> transformed_homo_vertices = apply_transform(homo_vertices, trafo, false);
|
||||
|
||||
// project back to current reference system
|
||||
const std::vector<Vec4d> homo_axes = { Vec4d::UnitX(), Vec4d::UnitY(), Vec4d::UnitZ() };
|
||||
std::vector<Vec4d> transformed_homo_axes = apply_transform(homo_axes, Geometry::Transformation(trafo).get_matrix_no_scaling_factor(), true);
|
||||
std::vector<Vec3d> transformed_axes(transformed_homo_axes.size());
|
||||
for (size_t i = 0; i < transformed_homo_axes.size(); ++i) {
|
||||
transformed_axes[i] = Vec4d_to_Vec3d(transformed_homo_axes[i]);
|
||||
}
|
||||
|
||||
Vec3d min = { DBL_MAX, DBL_MAX, DBL_MAX };
|
||||
Vec3d max = { -DBL_MAX, -DBL_MAX, -DBL_MAX };
|
||||
|
||||
for (const Vec4d& v_homo : transformed_homo_vertices) {
|
||||
const Vec3d v = Vec4d_to_Vec3d(v_homo);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const double dot_i = v.dot(transformed_axes[i]);
|
||||
min(i) = std::min(min(i), dot_i);
|
||||
max(i) = std::max(max(i), dot_i);
|
||||
}
|
||||
}
|
||||
|
||||
// return size
|
||||
const Vec3d size = max - min;
|
||||
return size;
|
||||
};
|
||||
|
||||
const Vec3d box_size = calc_box_size(original_box, trafo);
|
||||
const std::vector<Vec4d> box_center = { point_to_Vec4d(original_box.center()) };
|
||||
std::vector<Vec4d> transformed_box_center = apply_transform(box_center, trafo, false);
|
||||
|
||||
//
|
||||
// return box centered at 0, 0, 0
|
||||
//
|
||||
const Vec3d half_box_size = 0.5 * box_size;
|
||||
BoundingBoxf3 out_box(-half_box_size, half_box_size);
|
||||
Geometry::Transformation out_trafo(trafo);
|
||||
out_trafo.set_offset(Vec4d_to_Vec3d(transformed_box_center[0]));
|
||||
*const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>>*>(&m_bounding_box_in_current_reference_system) = { out_box, out_trafo.get_matrix_no_scaling_factor() };
|
||||
*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
|
||||
{
|
||||
BoundingBoxf3 original_box;
|
||||
Transform3d trafo;
|
||||
|
||||
//
|
||||
// calculate box aligned to current reference system
|
||||
//
|
||||
switch (type)
|
||||
{
|
||||
case ECoordinatesType::World:
|
||||
{
|
||||
original_box = get_bounding_box();
|
||||
trafo = Transform3d::Identity();
|
||||
break;
|
||||
}
|
||||
case ECoordinatesType::Instance: {
|
||||
for (unsigned int id : m_list) {
|
||||
const GLVolume& v = *get_volume(id);
|
||||
original_box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
|
||||
}
|
||||
trafo = get_first_volume()->get_instance_transformation().get_matrix();
|
||||
break;
|
||||
}
|
||||
case ECoordinatesType::Local: {
|
||||
assert(is_single_volume_or_modifier());
|
||||
const GLVolume& v = *get_first_volume();
|
||||
original_box = v.bounding_box();
|
||||
trafo = v.world_matrix();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// calculate box size in world coordinates
|
||||
//
|
||||
auto point_to_Vec4d = [](const Vec3d& p) { return Vec4d(p.x(), p.y(), p.z(), 1.0); };
|
||||
auto Vec4d_to_Vec3d = [](const Vec4d& v) { return Vec3d(v.x(), v.y(), v.z()); };
|
||||
|
||||
auto apply_transform = [](const std::vector<Vec4d>& original, const Transform3d& trafo, bool normalize) {
|
||||
std::vector<Vec4d> transformed(original.size());
|
||||
for (size_t i = 0; i < original.size(); ++i) {
|
||||
transformed[i] = trafo * original[i];
|
||||
if (normalize)
|
||||
transformed[i].normalize();
|
||||
}
|
||||
return transformed;
|
||||
};
|
||||
|
||||
auto calc_box_size = [point_to_Vec4d, Vec4d_to_Vec3d, apply_transform](const BoundingBoxf3& box, const Transform3d& trafo) {
|
||||
Geometry::Transformation transformation(trafo);
|
||||
|
||||
// box aligned to current reference system
|
||||
std::vector<Vec4d> homo_vertices = {
|
||||
point_to_Vec4d({ box.min.x(), box.min.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.min.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.max.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.min.x(), box.max.y(), box.min.z() }),
|
||||
point_to_Vec4d({ box.min.x(), box.min.y(), box.max.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.min.y(), box.max.z() }),
|
||||
point_to_Vec4d({ box.max.x(), box.max.y(), box.max.z() }),
|
||||
point_to_Vec4d({ box.min.x(), box.max.y(), box.max.z() })
|
||||
};
|
||||
|
||||
// box vertices in world coordinates
|
||||
std::vector<Vec4d> transformed_homo_vertices = apply_transform(homo_vertices, trafo, false);
|
||||
|
||||
// project back to current reference system
|
||||
const std::vector<Vec4d> homo_axes = { Vec4d::UnitX(), Vec4d::UnitY(), Vec4d::UnitZ() };
|
||||
std::vector<Vec4d> transformed_homo_axes = apply_transform(homo_axes, Geometry::Transformation(trafo).get_matrix_no_scaling_factor(), true);
|
||||
std::vector<Vec3d> transformed_axes(transformed_homo_axes.size());
|
||||
for (size_t i = 0; i < transformed_homo_axes.size(); ++i) {
|
||||
transformed_axes[i] = Vec4d_to_Vec3d(transformed_homo_axes[i]);
|
||||
}
|
||||
|
||||
Vec3d min = { DBL_MAX, DBL_MAX, DBL_MAX };
|
||||
Vec3d max = { -DBL_MAX, -DBL_MAX, -DBL_MAX };
|
||||
|
||||
for (const Vec4d& v_homo : transformed_homo_vertices) {
|
||||
const Vec3d v = Vec4d_to_Vec3d(v_homo);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const double dot_i = v.dot(transformed_axes[i]);
|
||||
min(i) = std::min(min(i), dot_i);
|
||||
max(i) = std::max(max(i), dot_i);
|
||||
}
|
||||
}
|
||||
|
||||
// return size
|
||||
const Vec3d size = max - min;
|
||||
return size;
|
||||
};
|
||||
|
||||
const Vec3d box_size = calc_box_size(original_box, trafo);
|
||||
const std::vector<Vec4d> box_center = { point_to_Vec4d(original_box.center()) };
|
||||
std::vector<Vec4d> transformed_box_center = apply_transform(box_center, trafo, false);
|
||||
|
||||
//
|
||||
// return box centered at 0, 0, 0
|
||||
//
|
||||
const Vec3d half_box_size = 0.5 * box_size;
|
||||
BoundingBoxf3 out_box(-half_box_size, half_box_size);
|
||||
Geometry::Transformation out_trafo(trafo);
|
||||
out_trafo.set_offset(Vec4d_to_Vec3d(transformed_box_center[0]));
|
||||
return { out_box, out_trafo.get_matrix_no_scaling_factor() };
|
||||
}
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
void Selection::setup_cache()
|
||||
|
@ -391,9 +391,12 @@ public:
|
||||
// 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;
|
||||
// Returns the bounding box aligned to the axis of the currently selected reference system (World/Object/Part)
|
||||
// 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;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
void setup_cache();
|
||||
|
Loading…
Reference in New Issue
Block a user