3D gizmos' grabber size as a function of selected objects size
This commit is contained in:
parent
a97df55592
commit
00b10c7f9d
@ -20,90 +20,91 @@ static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// 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)
|
||||
// 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)
|
||||
{
|
||||
Transform3d m = Transform3d::Identity();
|
||||
m.translate(-center);
|
||||
Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0));
|
||||
return Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0);
|
||||
}
|
||||
|
||||
// returns the intersection of the given ray with the plane parallel to plane XZ and passing through the given center
|
||||
// coordinates are local to the plane
|
||||
Vec3d intersection_on_plane_xz(const Linef3& ray, const Vec3d& center)
|
||||
{
|
||||
Transform3d m = Transform3d::Identity();
|
||||
m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX()));
|
||||
m.translate(-center);
|
||||
Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0));
|
||||
return Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1));
|
||||
}
|
||||
|
||||
// returns the intersection of the given ray with the plane parallel to plane YZ and passing through the given center
|
||||
// coordinates are local to the plane
|
||||
Vec3d intersection_on_plane_yz(const Linef3& ray, const Vec3d& center)
|
||||
{
|
||||
Transform3d m = Transform3d::Identity();
|
||||
m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY()));
|
||||
m.translate(-center);
|
||||
Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0));
|
||||
|
||||
return Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0));
|
||||
}
|
||||
|
||||
// return an index:
|
||||
// 0 for plane XY
|
||||
// 1 for plane XZ
|
||||
// 2 for plane YZ
|
||||
// which indicates which plane is best suited for intersecting the given unit vector
|
||||
// giving precedence to the plane with the given index
|
||||
unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_plane)
|
||||
{
|
||||
unsigned int ret = preferred_plane;
|
||||
|
||||
// 1st checks if the given vector is not parallel to the given preferred plane
|
||||
double dot_to_normal = 0.0;
|
||||
switch (ret)
|
||||
{
|
||||
Transform3d m = Transform3d::Identity();
|
||||
m.translate(-center);
|
||||
Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0));
|
||||
return Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0);
|
||||
case 0: // plane xy
|
||||
{
|
||||
dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitZ()));
|
||||
break;
|
||||
}
|
||||
case 1: // plane xz
|
||||
{
|
||||
dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY()));
|
||||
break;
|
||||
}
|
||||
case 2: // plane yz
|
||||
{
|
||||
dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// returns the intersection of the given ray with the plane parallel to plane XZ and passing through the given center
|
||||
// coordinates are local to the plane
|
||||
Vec3d intersection_on_plane_xz(const Linef3& ray, const Vec3d& center)
|
||||
// if almost parallel, select the plane whose normal direction is closest to the given vector direction,
|
||||
// otherwise return the given preferred plane index
|
||||
if (dot_to_normal < 0.1)
|
||||
{
|
||||
Transform3d m = Transform3d::Identity();
|
||||
m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX()));
|
||||
m.translate(-center);
|
||||
Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0));
|
||||
return Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1));
|
||||
typedef std::map<double, unsigned int> ProjsMap;
|
||||
ProjsMap projs_map;
|
||||
projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitZ())), 0)); // plane xy
|
||||
projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(-Vec3d::UnitY())), 1)); // plane xz
|
||||
projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitX())), 2)); // plane yz
|
||||
ret = projs_map.rbegin()->second;
|
||||
}
|
||||
|
||||
// returns the intersection of the given ray with the plane parallel to plane YZ and passing through the given center
|
||||
// coordinates are local to the plane
|
||||
Vec3d intersection_on_plane_yz(const Linef3& ray, const Vec3d& center)
|
||||
{
|
||||
Transform3d m = Transform3d::Identity();
|
||||
m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY()));
|
||||
m.translate(-center);
|
||||
Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0));
|
||||
|
||||
return Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0));
|
||||
}
|
||||
|
||||
// return an index:
|
||||
// 0 for plane XY
|
||||
// 1 for plane XZ
|
||||
// 2 for plane YZ
|
||||
// which indicates which plane is best suited for intersecting the given unit vector
|
||||
// giving precedence to the plane with the given index
|
||||
unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_plane)
|
||||
{
|
||||
unsigned int ret = preferred_plane;
|
||||
|
||||
// 1st checks if the given vector is not parallel to the given preferred plane
|
||||
double dot_to_normal = 0.0;
|
||||
switch (ret)
|
||||
{
|
||||
case 0: // plane xy
|
||||
{
|
||||
dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitZ()));
|
||||
break;
|
||||
}
|
||||
case 1: // plane xz
|
||||
{
|
||||
dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY()));
|
||||
break;
|
||||
}
|
||||
case 2: // plane yz
|
||||
{
|
||||
dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if almost parallel, select the plane whose normal direction is closest to the given vector direction,
|
||||
// otherwise return the given preferred plane index
|
||||
if (dot_to_normal < 0.1)
|
||||
{
|
||||
typedef std::map<double, unsigned int> ProjsMap;
|
||||
ProjsMap projs_map;
|
||||
projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitZ())), 0)); // plane xy
|
||||
projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(-Vec3d::UnitY())), 1)); // plane xz
|
||||
projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitX())), 2)); // plane yz
|
||||
ret = projs_map.rbegin()->second;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const float GLGizmoBase::Grabber::HalfSize = 2.0f;
|
||||
const float GLGizmoBase::Grabber::SizeFactor = 0.025f;
|
||||
const float GLGizmoBase::Grabber::MinHalfSize = 1.5f;
|
||||
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
|
||||
|
||||
GLGizmoBase::Grabber::Grabber()
|
||||
@ -117,7 +118,7 @@ GLGizmoBase::Grabber::Grabber()
|
||||
color[2] = 1.0f;
|
||||
}
|
||||
|
||||
void GLGizmoBase::Grabber::render(bool hover) const
|
||||
void GLGizmoBase::Grabber::render(bool hover, const BoundingBoxf3& box) const
|
||||
{
|
||||
float render_color[3];
|
||||
if (hover)
|
||||
@ -129,12 +130,15 @@ void GLGizmoBase::Grabber::render(bool hover) const
|
||||
else
|
||||
::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float));
|
||||
|
||||
render(render_color, true);
|
||||
render(box, render_color, true);
|
||||
}
|
||||
|
||||
void GLGizmoBase::Grabber::render(const float* render_color, bool use_lighting) const
|
||||
void GLGizmoBase::Grabber::render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const
|
||||
{
|
||||
float half_size = dragging ? HalfSize * DraggingScaleFactor : HalfSize;
|
||||
float max_size = (float)box.max_size();
|
||||
float half_size = dragging ? max_size * SizeFactor * DraggingScaleFactor : max_size * SizeFactor;
|
||||
half_size = std::max(half_size, MinHalfSize);
|
||||
|
||||
if (use_lighting)
|
||||
::glEnable(GL_LIGHTING);
|
||||
|
||||
@ -291,16 +295,16 @@ float GLGizmoBase::picking_color_component(unsigned int id) const
|
||||
return (float)color / 255.0f;
|
||||
}
|
||||
|
||||
void GLGizmoBase::render_grabbers() const
|
||||
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
|
||||
{
|
||||
for (int i = 0; i < (int)m_grabbers.size(); ++i)
|
||||
{
|
||||
if (m_grabbers[i].enabled)
|
||||
m_grabbers[i].render(m_hover_id == i);
|
||||
m_grabbers[i].render((m_hover_id == i), box);
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoBase::render_grabbers_for_picking() const
|
||||
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i)
|
||||
{
|
||||
@ -309,7 +313,7 @@ void GLGizmoBase::render_grabbers_for_picking() const
|
||||
m_grabbers[i].color[0] = 1.0f;
|
||||
m_grabbers[i].color[1] = 1.0f;
|
||||
m_grabbers[i].color[2] = picking_color_component(i);
|
||||
m_grabbers[i].render_for_picking();
|
||||
m_grabbers[i].render_for_picking(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -440,7 +444,7 @@ void GLGizmoRotate::on_render(const BoundingBoxf3& box) const
|
||||
if (m_hover_id != -1)
|
||||
render_angle();
|
||||
|
||||
render_grabber();
|
||||
render_grabber(box);
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
@ -452,7 +456,7 @@ void GLGizmoRotate::on_render_for_picking(const BoundingBoxf3& box) const
|
||||
::glPushMatrix();
|
||||
|
||||
transform_to_local();
|
||||
render_grabbers_for_picking();
|
||||
render_grabbers_for_picking(box);
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
@ -544,7 +548,7 @@ void GLGizmoRotate::render_angle() const
|
||||
::glEnd();
|
||||
}
|
||||
|
||||
void GLGizmoRotate::render_grabber() const
|
||||
void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
|
||||
{
|
||||
double grabber_radius = (double)(m_radius + GrabberOffset);
|
||||
m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0);
|
||||
@ -558,7 +562,7 @@ void GLGizmoRotate::render_grabber() const
|
||||
::glEnd();
|
||||
|
||||
::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float));
|
||||
render_grabbers();
|
||||
render_grabbers(box);
|
||||
}
|
||||
|
||||
void GLGizmoRotate::transform_to_local() const
|
||||
@ -829,7 +833,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
|
||||
render_grabbers_connection(4, 5);
|
||||
}
|
||||
// draw grabbers
|
||||
render_grabbers();
|
||||
render_grabbers(m_box);
|
||||
}
|
||||
else if ((m_hover_id == 0) || (m_hover_id == 1))
|
||||
{
|
||||
@ -846,8 +850,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
|
||||
::glColor3fv(m_grabbers[0].color);
|
||||
render_grabbers_connection(0, 1);
|
||||
// draw grabbers
|
||||
m_grabbers[0].render(true);
|
||||
m_grabbers[1].render(true);
|
||||
m_grabbers[0].render(true, m_box);
|
||||
m_grabbers[1].render(true, m_box);
|
||||
}
|
||||
else if ((m_hover_id == 2) || (m_hover_id == 3))
|
||||
{
|
||||
@ -864,8 +868,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
|
||||
::glColor3fv(m_grabbers[2].color);
|
||||
render_grabbers_connection(2, 3);
|
||||
// draw grabbers
|
||||
m_grabbers[2].render(true);
|
||||
m_grabbers[3].render(true);
|
||||
m_grabbers[2].render(true, m_box);
|
||||
m_grabbers[3].render(true, m_box);
|
||||
}
|
||||
else if ((m_hover_id == 4) || (m_hover_id == 5))
|
||||
{
|
||||
@ -882,8 +886,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
|
||||
::glColor3fv(m_grabbers[4].color);
|
||||
render_grabbers_connection(4, 5);
|
||||
// draw grabbers
|
||||
m_grabbers[4].render(true);
|
||||
m_grabbers[5].render(true);
|
||||
m_grabbers[4].render(true, m_box);
|
||||
m_grabbers[5].render(true, m_box);
|
||||
}
|
||||
else if (m_hover_id >= 6)
|
||||
{
|
||||
@ -899,7 +903,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
|
||||
// draw grabbers
|
||||
for (int i = 6; i < 10; ++i)
|
||||
{
|
||||
m_grabbers[i].render(true);
|
||||
m_grabbers[i].render(true, m_box);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -908,7 +912,7 @@ void GLGizmoScale3D::on_render_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
render_grabbers_for_picking();
|
||||
render_grabbers_for_picking(box);
|
||||
}
|
||||
|
||||
void GLGizmoScale3D::render_box(const BoundingBoxf3& box) const
|
||||
@ -1118,7 +1122,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const
|
||||
}
|
||||
|
||||
// draw grabbers
|
||||
render_grabbers();
|
||||
render_grabbers(box);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1130,7 +1134,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const
|
||||
::glEnd();
|
||||
|
||||
// draw grabber
|
||||
m_grabbers[m_hover_id].render(true);
|
||||
m_grabbers[m_hover_id].render(true, box);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1138,7 +1142,7 @@ void GLGizmoMove3D::on_render_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
render_grabbers_for_picking();
|
||||
render_grabbers_for_picking(box);
|
||||
}
|
||||
|
||||
double GLGizmoMove3D::calc_displacement(unsigned int preferred_plane_id, const Linef3& mouse_ray) const
|
||||
|
@ -22,7 +22,8 @@ class GLGizmoBase
|
||||
protected:
|
||||
struct Grabber
|
||||
{
|
||||
static const float HalfSize;
|
||||
static const float SizeFactor;
|
||||
static const float MinHalfSize;
|
||||
static const float DraggingScaleFactor;
|
||||
|
||||
Vec3d center;
|
||||
@ -33,11 +34,11 @@ protected:
|
||||
|
||||
Grabber();
|
||||
|
||||
void render(bool hover) const;
|
||||
void render_for_picking() const { render(color, false); }
|
||||
void render(bool hover, const BoundingBoxf3& box) const;
|
||||
void render_for_picking(const BoundingBoxf3& box) const { render(box, color, false); }
|
||||
|
||||
private:
|
||||
void render(const float* render_color, bool use_lighting) const;
|
||||
void render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const;
|
||||
void render_face(float half_size) const;
|
||||
};
|
||||
|
||||
@ -109,8 +110,8 @@ protected:
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0;
|
||||
|
||||
float picking_color_component(unsigned int id) const;
|
||||
void render_grabbers() const;
|
||||
void render_grabbers_for_picking() const;
|
||||
void render_grabbers(const BoundingBoxf3& box) const;
|
||||
void render_grabbers_for_picking(const BoundingBoxf3& box) const;
|
||||
|
||||
void set_tooltip(const std::string& tooltip) const;
|
||||
std::string format(float value, unsigned int decimals) const;
|
||||
@ -163,7 +164,7 @@ private:
|
||||
void render_snap_radii() const;
|
||||
void render_reference_radius() const;
|
||||
void render_angle() const;
|
||||
void render_grabber() const;
|
||||
void render_grabber(const BoundingBoxf3& box) const;
|
||||
|
||||
void transform_to_local() const;
|
||||
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
|
||||
|
Loading…
Reference in New Issue
Block a user