Created a new gizmo for flattening an object
This commit is contained in:
parent
a06b6716ea
commit
25a6c7e30e
@ -141,8 +141,9 @@ sub new {
|
|||||||
|
|
||||||
# callback to react to gizmo rotate
|
# callback to react to gizmo rotate
|
||||||
my $on_gizmo_rotate = sub {
|
my $on_gizmo_rotate = sub {
|
||||||
my ($angle_z) = @_;
|
my ($angle_z, $angle_y) = @_;
|
||||||
$self->rotate(rad2deg($angle_z), Z, 'absolute');
|
$self->rotate(rad2deg($angle_z), Z, 'absolute');
|
||||||
|
$self->rotate(rad2deg($angle_y), Y, 'absolute');
|
||||||
};
|
};
|
||||||
|
|
||||||
# callback to update object's geometry info while using gizmos
|
# callback to update object's geometry info while using gizmos
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "GLCanvas3D.hpp"
|
#include "GLCanvas3D.hpp"
|
||||||
|
|
||||||
|
#include "../../admesh/stl.h"
|
||||||
#include "../../libslic3r/libslic3r.h"
|
#include "../../libslic3r/libslic3r.h"
|
||||||
#include "../../slic3r/GUI/3DScene.hpp"
|
#include "../../slic3r/GUI/3DScene.hpp"
|
||||||
#include "../../slic3r/GUI/GLShader.hpp"
|
#include "../../slic3r/GUI/GLShader.hpp"
|
||||||
@ -1154,6 +1155,18 @@ bool GLCanvas3D::Gizmos::init()
|
|||||||
|
|
||||||
m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo));
|
m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo));
|
||||||
|
|
||||||
|
gizmo = new GLGizmoFlatten;
|
||||||
|
if (gizmo == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!gizmo->init()) {
|
||||||
|
_reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo));
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1387,6 +1400,25 @@ void GLCanvas3D::Gizmos::set_angle_z(float angle_z)
|
|||||||
reinterpret_cast<GLGizmoRotate*>(it->second)->set_angle_z(angle_z);
|
reinterpret_cast<GLGizmoRotate*>(it->second)->set_angle_z(angle_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pointf3 GLCanvas3D::Gizmos::get_flattening_normal() const
|
||||||
|
{
|
||||||
|
if (!m_enabled)
|
||||||
|
return Pointf3(0.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
GizmosMap::const_iterator it = m_gizmos.find(Flatten);
|
||||||
|
return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoFlatten*>(it->second)->get_flattening_normal() : Pointf3(0.f, 0.f, 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::Gizmos::set_flattening_data(std::vector<Pointf3s> vertices_list)
|
||||||
|
{
|
||||||
|
if (!m_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GizmosMap::const_iterator it = m_gizmos.find(Flatten);
|
||||||
|
if (it != m_gizmos.end())
|
||||||
|
reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(vertices_list);
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::Gizmos::render(const GLCanvas3D& canvas, const BoundingBoxf3& box) const
|
void GLCanvas3D::Gizmos::render(const GLCanvas3D& canvas, const BoundingBoxf3& box) const
|
||||||
{
|
{
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
@ -2170,6 +2202,27 @@ void GLCanvas3D::update_gizmos_data()
|
|||||||
{
|
{
|
||||||
m_gizmos.set_scale(model_instance->scaling_factor);
|
m_gizmos.set_scale(model_instance->scaling_factor);
|
||||||
m_gizmos.set_angle_z(model_instance->rotation);
|
m_gizmos.set_angle_z(model_instance->rotation);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
// Following block provides convex hull data to the Flatten gizmo
|
||||||
|
// It is temporary, it should be optimized and moved elsewhere later
|
||||||
|
TriangleMesh ch = model_object->mesh().convex_hull3d();
|
||||||
|
stl_facet* facet_ptr = ch.stl.facet_start;
|
||||||
|
std::vector<Pointf3s> points;
|
||||||
|
while (facet_ptr < ch.stl.facet_start+ch.stl.stats.number_of_facets) {
|
||||||
|
Pointf3 a = Pointf3(facet_ptr->vertex[1].x - facet_ptr->vertex[0].x, facet_ptr->vertex[1].y - facet_ptr->vertex[0].y, facet_ptr->vertex[1].z - facet_ptr->vertex[0].z);
|
||||||
|
Pointf3 b = Pointf3(facet_ptr->vertex[2].x - facet_ptr->vertex[0].x, facet_ptr->vertex[2].y - facet_ptr->vertex[0].y, facet_ptr->vertex[2].z - facet_ptr->vertex[0].z);
|
||||||
|
|
||||||
|
if (0.5 * sqrt(dot(cross(a, b), cross(a,b))) > 50.f) {
|
||||||
|
points.emplace_back(Pointf3s());
|
||||||
|
for (unsigned int j=0; j<3; ++j)
|
||||||
|
points.back().emplace_back(Pointf3(facet_ptr->vertex[j].x, facet_ptr->vertex[j].y, facet_ptr->vertex[j].z));
|
||||||
|
points.back().emplace_back(Pointf3(facet_ptr->normal.x, facet_ptr->normal.y, facet_ptr->normal.z));
|
||||||
|
}
|
||||||
|
facet_ptr+=1;
|
||||||
|
}
|
||||||
|
m_gizmos.set_flattening_data(points);
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2177,6 +2230,7 @@ void GLCanvas3D::update_gizmos_data()
|
|||||||
{
|
{
|
||||||
m_gizmos.set_scale(1.0f);
|
m_gizmos.set_scale(1.0f);
|
||||||
m_gizmos.set_angle_z(0.0f);
|
m_gizmos.set_angle_z(0.0f);
|
||||||
|
m_gizmos.set_flattening_data(std::vector<Pointf3s>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2760,6 +2814,16 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
m_gizmos.start_dragging();
|
m_gizmos.start_dragging();
|
||||||
m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(selected_object_idx);
|
m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(selected_object_idx);
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
|
|
||||||
|
if (m_gizmos.get_current_type() == Gizmos::Flatten) {
|
||||||
|
// Rotate the object so the normal points downward:
|
||||||
|
Pointf3 normal = m_gizmos.get_flattening_normal();
|
||||||
|
if (normal.x != 0.f || normal.y != 0.f || normal.z != 0.f) {
|
||||||
|
float angle_z = -atan2(normal.y, normal.x);
|
||||||
|
float angle_y = M_PI - atan2(normal.x*cos(angle_z)-normal.y*sin(angle_z), normal.z);
|
||||||
|
m_on_gizmo_rotate_callback.call((double)angle_z, (double)angle_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3039,7 +3103,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
}
|
}
|
||||||
case Gizmos::Rotate:
|
case Gizmos::Rotate:
|
||||||
{
|
{
|
||||||
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
|
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z(), 0.);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -338,6 +338,7 @@ public:
|
|||||||
Undefined,
|
Undefined,
|
||||||
Scale,
|
Scale,
|
||||||
Rotate,
|
Rotate,
|
||||||
|
Flatten,
|
||||||
Num_Types
|
Num_Types
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -382,6 +383,9 @@ public:
|
|||||||
float get_angle_z() const;
|
float get_angle_z() const;
|
||||||
void set_angle_z(float angle_z);
|
void set_angle_z(float angle_z);
|
||||||
|
|
||||||
|
void set_flattening_data(std::vector<Pointf3s> vertices_list);
|
||||||
|
Pointf3 get_flattening_normal() const;
|
||||||
|
|
||||||
void render(const GLCanvas3D& canvas, const BoundingBoxf3& box) const;
|
void render(const GLCanvas3D& canvas, const BoundingBoxf3& box) const;
|
||||||
void render_current_gizmo_for_picking_pass(const BoundingBoxf3& box) const;
|
void render_current_gizmo_for_picking_pass(const BoundingBoxf3& box) const;
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ int GLGizmoBase::get_hover_id() const
|
|||||||
|
|
||||||
void GLGizmoBase::set_hover_id(int id)
|
void GLGizmoBase::set_hover_id(int id)
|
||||||
{
|
{
|
||||||
if (id < (int)m_grabbers.size())
|
//if (id < (int)m_grabbers.size())
|
||||||
m_hover_id = id;
|
m_hover_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,5 +502,112 @@ void GLGizmoScale::on_render_for_picking(const BoundingBoxf3& box) const
|
|||||||
render_grabbers();
|
render_grabbers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLGizmoFlatten::GLGizmoFlatten()
|
||||||
|
: GLGizmoBase(),
|
||||||
|
m_normal(Pointf3(0.f, 0.f, 0.f))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
bool GLGizmoFlatten::on_init()
|
||||||
|
{
|
||||||
|
std::string path = resources_dir() + "/icons/overlay/";
|
||||||
|
|
||||||
|
std::string filename = path + "scale_off.png";
|
||||||
|
if (!m_textures[Off].load_from_file(filename, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
filename = path + "scale_hover.png";
|
||||||
|
if (!m_textures[Hover].load_from_file(filename, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
filename = path + "scale_on.png";
|
||||||
|
if (!m_textures[On].load_from_file(filename, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFlatten::on_start_dragging()
|
||||||
|
{
|
||||||
|
if (m_hover_id != -1)
|
||||||
|
m_normal = m_planes[m_hover_id].normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFlatten::on_update(const Pointf& mouse_pos)
|
||||||
|
{
|
||||||
|
/*Pointf center(0.5 * (m_grabbers[1].center.x + m_grabbers[0].center.x), 0.5 * (m_grabbers[3].center.y + m_grabbers[0].center.y));
|
||||||
|
|
||||||
|
coordf_t orig_len = length(m_starting_drag_position - center);
|
||||||
|
coordf_t new_len = length(mouse_pos - center);
|
||||||
|
coordf_t ratio = (orig_len != 0.0) ? new_len / orig_len : 1.0;
|
||||||
|
|
||||||
|
m_scale = m_starting_scale * (float)ratio;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const
|
||||||
|
{
|
||||||
|
bool blending_was_enabled = ::glIsEnabled(GL_BLEND);
|
||||||
|
::glEnable(GL_BLEND);
|
||||||
|
::glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
for (int i=0; i<(int)m_planes.size(); ++i) {
|
||||||
|
if (i == m_hover_id)
|
||||||
|
::glColor4f(0.9f, 0.9f, 0.9f, 0.75f);
|
||||||
|
else
|
||||||
|
::glColor4f(0.9f, 0.9f, 0.9f, 0.5f);
|
||||||
|
|
||||||
|
::glBegin(GL_POLYGON);
|
||||||
|
for (const auto& vertex : m_planes[i].vertices)
|
||||||
|
::glVertex3f((GLfloat)vertex.x, (GLfloat)vertex.y, (GLfloat)vertex.z);
|
||||||
|
::glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blending_was_enabled)
|
||||||
|
::glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const
|
||||||
|
{
|
||||||
|
static const GLfloat INV_255 = 1.0f / 255.0f;
|
||||||
|
|
||||||
|
::glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < m_planes.size(); ++i)
|
||||||
|
{
|
||||||
|
::glColor3f(1.f, 1.f, (254.0f - (float)i) * INV_255);
|
||||||
|
::glBegin(GL_POLYGON);
|
||||||
|
for (const auto& vertex : m_planes[i].vertices)
|
||||||
|
::glVertex3f((GLfloat)vertex.x, (GLfloat)vertex.y, (GLfloat)vertex.z);
|
||||||
|
::glEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFlatten::set_flattening_data(std::vector<Pointf3s> vertices_list)
|
||||||
|
{
|
||||||
|
// Each entry in vertices_list describe one polygon that can be laid flat.
|
||||||
|
// All points but the last one are vertices of the polygon, the last "point" is the outer normal vector.
|
||||||
|
|
||||||
|
m_planes.clear();
|
||||||
|
m_planes.reserve(vertices_list.size());
|
||||||
|
|
||||||
|
for (const auto& plane_data : vertices_list) {
|
||||||
|
m_planes.emplace_back(PlaneData());
|
||||||
|
for (unsigned int i=0; i<plane_data.size()-1; ++i)
|
||||||
|
m_planes.back().vertices.emplace_back(plane_data[i]);
|
||||||
|
m_planes.back().normal = plane_data.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pointf3 GLGizmoFlatten::get_flattening_normal() const {
|
||||||
|
Pointf3 normal = m_normal;
|
||||||
|
m_normal = Pointf3(0.f, 0.f, 0.f);
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -149,6 +149,38 @@ protected:
|
|||||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const;
|
virtual void on_render_for_picking(const BoundingBoxf3& box) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GLGizmoFlatten : public GLGizmoBase
|
||||||
|
{
|
||||||
|
// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself.
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Pointf3 m_normal;
|
||||||
|
|
||||||
|
struct PlaneData {
|
||||||
|
std::vector<Pointf3> vertices;
|
||||||
|
Pointf3 normal;
|
||||||
|
float color[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<PlaneData> m_planes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GLGizmoFlatten();
|
||||||
|
|
||||||
|
void set_flattening_data(std::vector<Pointf3s> vertices_list);
|
||||||
|
Pointf3 get_flattening_normal() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool on_init();
|
||||||
|
virtual void on_start_dragging();
|
||||||
|
virtual void on_update(const Pointf& mouse_pos);
|
||||||
|
virtual void on_render(const BoundingBoxf3& box) const;
|
||||||
|
virtual void on_render_for_picking(const BoundingBoxf3& box) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user