Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'xs/src/slic3r/GUI/GLGizmo.cpp')
-rw-r--r--xs/src/slic3r/GUI/GLGizmo.cpp255
1 files changed, 141 insertions, 114 deletions
diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp
index 4aa5ab32f..e23958c1d 100644
--- a/xs/src/slic3r/GUI/GLGizmo.cpp
+++ b/xs/src/slic3r/GUI/GLGizmo.cpp
@@ -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;
}
-
- // 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)
+ case 1: // plane xz
{
- 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));
+ dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY()));
+ break;
}
-
- // 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)
+ case 2: // plane yz
{
- 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));
+ dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX()));
+ break;
}
-
- // 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)
+ default:
{
- 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;
- }
+ break;
+ }
+ }
- return ret;
+ // 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;
+}
- 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
@@ -689,6 +693,7 @@ void GLGizmoRotate3D::on_render(const BoundingBoxf3& box) const
}
const float GLGizmoScale3D::Offset = 5.0f;
+const Vec3d GLGizmoScale3D::OffsetVec = (double)GLGizmoScale3D::Offset * Vec3d::Ones();
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent)
: GLGizmoBase(parent)
@@ -738,7 +743,7 @@ void GLGizmoScale3D::on_start_dragging(const BoundingBoxf3& box)
{
m_starting_drag_position = m_grabbers[m_hover_id].center;
m_show_starting_box = true;
- m_starting_box = box;
+ m_starting_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec);
}
}
@@ -772,9 +777,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
::glEnable(GL_DEPTH_TEST);
- Vec3d offset_vec = (double)Offset * Vec3d::Ones();
-
- m_box = BoundingBoxf3(box.min - offset_vec, box.max + offset_vec);
+ m_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec);
const Vec3d& center = m_box.center();
// x axis
@@ -829,7 +832,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 +849,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 +867,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 +885,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 +902,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 +911,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
@@ -1029,6 +1032,7 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent)
, m_position(Vec3d::Zero())
, m_starting_drag_position(Vec3d::Zero())
, m_starting_box_center(Vec3d::Zero())
+ , m_starting_box_bottom_center(Vec3d::Zero())
{
}
@@ -1062,17 +1066,19 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box)
{
m_starting_drag_position = 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);
}
}
void GLGizmoMove3D::on_update(const Linef3& mouse_ray)
{
if (m_hover_id == 0)
- m_position(0) = 2.0 * m_starting_box_center(0) + calc_displacement(1, mouse_ray) - m_starting_drag_position(0);
+ m_position(0) = 2.0 * m_starting_box_center(0) + calc_projection(X, 1, mouse_ray) - m_starting_drag_position(0);
else if (m_hover_id == 1)
- m_position(1) = 2.0 * m_starting_box_center(1) + calc_displacement(2, mouse_ray) - m_starting_drag_position(1);
+ m_position(1) = 2.0 * m_starting_box_center(1) + calc_projection(Y, 2, mouse_ray) - m_starting_drag_position(1);
else if (m_hover_id == 2)
- m_position(2) = 2.0 * m_starting_box_center(2) + calc_displacement(1, mouse_ray) - m_starting_drag_position(2);
+ m_position(2) = 2.0 * m_starting_box_bottom_center(2) + calc_projection(Z, 1, mouse_ray) - m_starting_drag_position(2);
}
void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const
@@ -1118,7 +1124,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const
}
// draw grabbers
- render_grabbers();
+ render_grabbers(box);
}
else
{
@@ -1130,7 +1136,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,43 +1144,43 @@ 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
+double GLGizmoMove3D::calc_projection(Axis axis, unsigned int preferred_plane_id, const Linef3& mouse_ray) const
{
- double displacement = 0.0;
+ double projection = 0.0;
- Vec3d starting_vec = m_starting_drag_position - m_starting_box_center;
+ Vec3d starting_vec = (axis == Z) ? m_starting_drag_position - m_starting_box_bottom_center : m_starting_drag_position - m_starting_box_center;
double len_starting_vec = starting_vec.norm();
if (len_starting_vec == 0.0)
- return displacement;
+ return projection;
Vec3d starting_vec_dir = starting_vec.normalized();
Vec3d mouse_dir = mouse_ray.unit_vector();
unsigned int plane_id = select_best_plane(mouse_dir, preferred_plane_id);
- switch (plane_id)
+ switch (plane_id)
{
case 0:
{
- displacement = starting_vec_dir.dot(intersection_on_plane_xy(mouse_ray, m_starting_box_center));
+ projection = starting_vec_dir.dot(intersection_on_plane_xy(mouse_ray, (axis == Z) ? m_starting_box_bottom_center : m_starting_box_center));
break;
}
case 1:
{
- displacement = starting_vec_dir.dot(intersection_on_plane_xz(mouse_ray, m_starting_box_center));
+ projection = starting_vec_dir.dot(intersection_on_plane_xz(mouse_ray, (axis == Z) ? m_starting_box_bottom_center : m_starting_box_center));
break;
}
case 2:
{
- displacement = starting_vec_dir.dot(intersection_on_plane_yz(mouse_ray, m_starting_box_center));
+ projection = starting_vec_dir.dot(intersection_on_plane_yz(mouse_ray, (axis == Z) ? m_starting_box_bottom_center : m_starting_box_center));
break;
}
}
- return displacement;
+ return projection;
}
GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent)
@@ -1230,10 +1236,19 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const
else
::glColor4f(0.9f, 0.9f, 0.9f, 0.5f);
+#if ENABLE_MODELINSTANCE_3D_OFFSET
+ for (Vec3d offset : m_instances_positions) {
+ offset += dragged_offset;
+#else
for (Vec2d offset : m_instances_positions) {
offset += to_2d(dragged_offset);
+#endif // ENABLE_MODELINSTANCE_3D_OFFSET
::glPushMatrix();
+#if ENABLE_MODELINSTANCE_3D_OFFSET
+ ::glTranslated(offset(0), offset(1), offset(2));
+#else
::glTranslatef((GLfloat)offset(0), (GLfloat)offset(1), 0.0f);
+#endif // ENABLE_MODELINSTANCE_3D_OFFSET
::glBegin(GL_POLYGON);
for (const Vec3d& vertex : m_planes[i].vertices)
::glVertex3f((GLfloat)vertex(0), (GLfloat)vertex(1), (GLfloat)vertex(2));
@@ -1252,9 +1267,17 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const
for (unsigned int i = 0; i < m_planes.size(); ++i)
{
::glColor3f(1.0f, 1.0f, picking_color_component(i));
+#if ENABLE_MODELINSTANCE_3D_OFFSET
+ for (const Vec3d& offset : m_instances_positions) {
+#else
for (const Vec2d& offset : m_instances_positions) {
+#endif // ENABLE_MODELINSTANCE_3D_OFFSET
::glPushMatrix();
+#if ENABLE_MODELINSTANCE_3D_OFFSET
+ ::glTranslated(offset(0), offset(1), offset(2));
+#else
::glTranslatef((GLfloat)offset(0), (GLfloat)offset(1), 0.0f);
+#endif // ENABLE_MODELINSTANCE_3D_OFFSET
::glBegin(GL_POLYGON);
for (const Vec3d& vertex : m_planes[i].vertices)
::glVertex3f((GLfloat)vertex(0), (GLfloat)vertex(1), (GLfloat)vertex(2));
@@ -1272,7 +1295,11 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
if (m_model_object && !m_model_object->instances.empty()) {
m_instances_positions.clear();
for (const auto* instance : m_model_object->instances)
+#if ENABLE_MODELINSTANCE_3D_OFFSET
+ m_instances_positions.emplace_back(instance->get_offset());
+#else
m_instances_positions.emplace_back(instance->offset);
+#endif // ENABLE_MODELINSTANCE_3D_OFFSET
}
if (is_plane_update_necessary())