Simplified algorithm for update of gizmo move and scale

This commit is contained in:
Enrico Turri 2018-10-15 15:21:37 +02:00
parent 404ef147b3
commit adf739cd45
3 changed files with 85 additions and 7 deletions

View File

@ -13,7 +13,7 @@
// Uses a unique opengl context
#define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0)
// New selections
#define ENABLE_EXTENDED_SELECTION (0 && ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM)
#define ENABLE_EXTENDED_SELECTION (1 && ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM)
#endif // _technologies_h_

View File

@ -23,6 +23,7 @@ static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f
namespace Slic3r {
namespace GUI {
#if !ENABLE_EXTENDED_SELECTION
// returns the intersection of the given ray with the plane parallel to plane XY and passing through the given center
// coordinates are local to the plane
Vec3d intersection_on_plane_xy(const Linef3& ray, const Vec3d& center)
@ -105,7 +106,8 @@ unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_
return ret;
}
#endif // !ENABLE_EXTENDED_SELECTION
const float GLGizmoBase::Grabber::SizeFactor = 0.025f;
const float GLGizmoBase::Grabber::MinHalfSize = 1.5f;
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
@ -1065,7 +1067,11 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int
void GLGizmoScale3D::do_scale_x(const Linef3& mouse_ray)
{
#if ENABLE_EXTENDED_SELECTION
double ratio = calc_ratio(mouse_ray);
#else
double ratio = calc_ratio(1, mouse_ray, m_starting_box.center());
#endif // ENABLE_EXTENDED_SELECTION
if (ratio > 0.0)
m_scale(0) = m_starting_scale(0) * ratio;
@ -1073,7 +1079,11 @@ void GLGizmoScale3D::do_scale_x(const Linef3& mouse_ray)
void GLGizmoScale3D::do_scale_y(const Linef3& mouse_ray)
{
#if ENABLE_EXTENDED_SELECTION
double ratio = calc_ratio(mouse_ray);
#else
double ratio = calc_ratio(2, mouse_ray, m_starting_box.center());
#endif // ENABLE_EXTENDED_SELECTION
if (ratio > 0.0)
#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@ -1085,7 +1095,11 @@ void GLGizmoScale3D::do_scale_y(const Linef3& mouse_ray)
void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray)
{
#if ENABLE_EXTENDED_SELECTION
double ratio = calc_ratio(mouse_ray);
#else
double ratio = calc_ratio(1, mouse_ray, m_starting_box.center());
#endif // ENABLE_EXTENDED_SELECTION
if (ratio > 0.0)
#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@ -1097,16 +1111,46 @@ void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray)
void GLGizmoScale3D::do_scale_uniform(const Linef3& mouse_ray)
{
#if ENABLE_EXTENDED_SELECTION
double ratio = calc_ratio(mouse_ray);
#else
Vec3d center = m_starting_box.center();
#if !ENABLE_EXTENDED_SELECTION
center(2) = m_box.min(2);
#endif // !ENABLE_EXTENDED_SELECTION
double ratio = calc_ratio(0, mouse_ray, center);
#endif // ENABLE_EXTENDED_SELECTION
if (ratio > 0.0)
m_scale = m_starting_scale * ratio;
}
#if ENABLE_EXTENDED_SELECTION
double GLGizmoScale3D::calc_ratio(const Linef3& mouse_ray) const
{
double ratio = 0.0;
// vector from the center to the starting position
Vec3d starting_vec = m_starting_drag_position - m_starting_box.center();
double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0)
{
Vec3d mouse_dir = mouse_ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = mouse_ray.a + (m_starting_drag_position - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_starting_drag_position;
// finds projection of the vector along the staring direction
double proj = inters_vec.dot(starting_vec.normalized());
return (len_starting_vec + proj) / len_starting_vec;
}
return ratio;
}
#else
double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Vec3d& center) const
{
double ratio = 0.0;
@ -1142,6 +1186,7 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3&
return ratio;
}
#endif // ENABLE_EXTENDED_SELECTION
const double GLGizmoMove3D::Offset = 10.0;
@ -1209,11 +1254,11 @@ void GLGizmoMove3D::on_update(const Linef3& mouse_ray)
{
#if ENABLE_EXTENDED_SELECTION
if (m_hover_id == 0)
m_displacement(0) = calc_projection(X, 1, mouse_ray) - (m_starting_drag_position(0) - m_starting_box_center(0));
m_displacement(0) = calc_projection(mouse_ray);
else if (m_hover_id == 1)
m_displacement(1) = calc_projection(Y, 2, mouse_ray) - (m_starting_drag_position(1) - m_starting_box_center(1));
m_displacement(1) = calc_projection(mouse_ray);
else if (m_hover_id == 2)
m_displacement(2) = calc_projection(Z, 1, mouse_ray) - (m_starting_drag_position(2) - m_starting_box_bottom_center(2));
m_displacement(2) = calc_projection(mouse_ray);
#else
if (m_hover_id == 0)
m_position(0) = 2.0 * m_starting_box_center(0) + calc_projection(X, 1, mouse_ray) - m_starting_drag_position(0);
@ -1315,6 +1360,30 @@ void GLGizmoMove3D::on_render_for_picking(const BoundingBoxf3& box) const
}
#endif // ENABLE_EXTENDED_SELECTION
#if ENABLE_EXTENDED_SELECTION
double GLGizmoMove3D::calc_projection(const Linef3& mouse_ray) const
{
double projection = 0.0;
Vec3d starting_vec = m_starting_drag_position - m_starting_box_center;
double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0)
{
Vec3d mouse_dir = mouse_ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = mouse_ray.a + (m_starting_drag_position - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_starting_drag_position;
// finds projection of the vector along the staring direction
projection = inters_vec.dot(starting_vec.normalized());
}
return projection;
}
#else
double GLGizmoMove3D::calc_projection(Axis axis, unsigned int preferred_plane_id, const Linef3& mouse_ray) const
{
double projection = 0.0;
@ -1350,6 +1419,7 @@ double GLGizmoMove3D::calc_projection(Axis axis, unsigned int preferred_plane_id
return projection;
}
#endif // ENABLE_EXTENDED_SELECTION
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent)
: GLGizmoBase(parent)

View File

@ -376,7 +376,11 @@ private:
void do_scale_z(const Linef3& mouse_ray);
void do_scale_uniform(const Linef3& mouse_ray);
#if ENABLE_EXTENDED_SELECTION
double calc_ratio(const Linef3& mouse_ray) const;
#else
double calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Vec3d& center) const;
#endif // ENABLE_EXTENDED_SELECTION
};
class GLGizmoMove3D : public GLGizmoBase
@ -419,7 +423,11 @@ protected:
#endif // ENABLE_EXTENDED_SELECTION
private:
#if ENABLE_EXTENDED_SELECTION
double calc_projection(const Linef3& mouse_ray) const;
#else
double calc_projection(Axis axis, unsigned int preferred_plane_id, const Linef3& mouse_ray) const;
#endif // ENABLE_EXTENDED_SELECTION
};
class GLGizmoFlatten : public GLGizmoBase