SLA support points gizmo - multiple instance support

This commit is contained in:
Lukas Matena 2018-11-26 10:49:25 +01:00
parent e038c3a20d
commit d28d4823e0
6 changed files with 84 additions and 67 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,3 +1,4 @@
#include "slic3r/GUI/GLGizmo.hpp"
#include "GLCanvas3D.hpp" #include "GLCanvas3D.hpp"
#include "admesh/stl.h" #include "admesh/stl.h"
@ -7,7 +8,6 @@
#include "slic3r/GUI/GLShader.hpp" #include "slic3r/GUI/GLShader.hpp"
#include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/PresetBundle.hpp" #include "slic3r/GUI/PresetBundle.hpp"
#include "slic3r/GUI/GLGizmo.hpp"
#include "libslic3r/ClipperUtils.hpp" #include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/PrintConfig.hpp" #include "libslic3r/PrintConfig.hpp"
#include "libslic3r/GCode/PreviewData.hpp" #include "libslic3r/GCode/PreviewData.hpp"

View File

@ -738,7 +738,6 @@ private:
wxWindow *m_external_gizmo_widgets_parent; wxWindow *m_external_gizmo_widgets_parent;
#endif // not ENABLE_IMGUI #endif // not ENABLE_IMGUI
void post_event(wxEvent &&event);
void viewport_changed(); void viewport_changed();
public: public:
@ -752,6 +751,7 @@ public:
wxGLCanvas* get_wxglcanvas() { return m_canvas; } wxGLCanvas* get_wxglcanvas() { return m_canvas; }
bool init(bool useVBOs, bool use_legacy_opengl); bool init(bool useVBOs, bool use_legacy_opengl);
void post_event(wxEvent &&event);
#if !ENABLE_USE_UNIQUE_GLCONTEXT #if !ENABLE_USE_UNIQUE_GLCONTEXT
bool set_current(); bool set_current();

View File

@ -10,7 +10,6 @@
#include <Eigen/Dense> #include <Eigen/Dense>
#include "libslic3r/Geometry.hpp" #include "libslic3r/Geometry.hpp"
#include <igl/unproject_onto_mesh.h>
#include <GL/glew.h> #include <GL/glew.h>
#include <SLA/SLASupportTree.hpp> #include <SLA/SLASupportTree.hpp>
@ -1627,7 +1626,11 @@ void GLGizmoSlaSupports::set_model_object_ptr(ModelObject* model_object)
{ {
m_starting_center = Vec3d::Zero(); m_starting_center = Vec3d::Zero();
m_model_object = model_object; m_model_object = model_object;
m_model_object_matrix = model_object->instances.front()->get_matrix();
int selected_instance = m_parent.get_selection().get_instance_idx();
assert(selected_instance < (int)model_object->instances.size());
m_instance_matrix = model_object->instances[selected_instance]->get_matrix();
if (is_mesh_update_necessary()) if (is_mesh_update_necessary())
update_mesh(); update_mesh();
} }
@ -1639,7 +1642,7 @@ void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const
::glEnable(GL_DEPTH_TEST); ::glEnable(GL_DEPTH_TEST);
// the dragged_offset is a vector measuring where was the object moved // the dragged_offset is a vector measuring where was the object moved
// with the gizmo being on. This is reset in set_flattening_data and // with the gizmo being on. This is reset in set_model_object_ptr and
// does not work correctly when there are multiple copies. // does not work correctly when there are multiple copies.
if (m_starting_center == Vec3d::Zero()) if (m_starting_center == Vec3d::Zero())
@ -1653,7 +1656,7 @@ void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const
} }
::glPushMatrix(); ::glPushMatrix();
::glTranslatef((GLfloat)dragged_offset(0), (GLfloat)dragged_offset(1), (GLfloat)dragged_offset(2)); //::glTranslatef((GLfloat)dragged_offset(0), (GLfloat)dragged_offset(1), (GLfloat)dragged_offset(2));
render_grabbers(); render_grabbers();
::glPopMatrix(); ::glPopMatrix();
@ -1675,33 +1678,35 @@ void GLGizmoSlaSupports::on_render_for_picking(const GLCanvas3D::Selection& sele
void GLGizmoSlaSupports::render_grabbers(bool picking) const void GLGizmoSlaSupports::render_grabbers(bool picking) const
{ {
for (int i = 0; i < (int)m_grabbers.size(); ++i) for (const ModelInstance* inst : m_model_object->instances) {
{ for (int i = 0; i < (int)m_grabbers.size(); ++i)
if (!m_grabbers[i].enabled) {
continue; if (!m_grabbers[i].enabled)
continue;
float render_color[3]; float render_color[3];
if (!picking && m_hover_id == i) { if (!picking && m_hover_id == i) {
render_color[0] = 1.0f - m_grabbers[i].color[0]; render_color[0] = 1.0f - m_grabbers[i].color[0];
render_color[1] = 1.0f - m_grabbers[i].color[1]; render_color[1] = 1.0f - m_grabbers[i].color[1];
render_color[2] = 1.0f - m_grabbers[i].color[2]; render_color[2] = 1.0f - m_grabbers[i].color[2];
}
else
::memcpy((void*)render_color, (const void*)m_grabbers[i].color, 3 * sizeof(float));
if (!picking)
::glEnable(GL_LIGHTING);
::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]);
::glPushMatrix();
Vec3d center = inst->get_matrix() * m_grabbers[i].center;
::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2));
GLUquadricObj *quadric;
quadric = ::gluNewQuadric();
::gluQuadricDrawStyle(quadric, GLU_FILL );
::gluSphere( quadric , 0.75f, 36 , 18 );
::gluDeleteQuadric(quadric);
::glPopMatrix();
if (!picking)
::glDisable(GL_LIGHTING);
} }
else
::memcpy((void*)render_color, (const void*)m_grabbers[i].color, 3 * sizeof(float));
if (!picking)
::glEnable(GL_LIGHTING);
::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]);
::glPushMatrix();
Vec3d center = m_model_object_matrix * m_grabbers[i].center;
::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2));
GLUquadricObj *quadric;
quadric = ::gluNewQuadric();
::gluQuadricDrawStyle(quadric, GLU_FILL );
::gluSphere( quadric , 0.75f, 36 , 18 );
::gluDeleteQuadric(quadric);
::glPopMatrix();
if (!picking)
::glDisable(GL_LIGHTING);
} }
} }
@ -1710,7 +1715,7 @@ bool GLGizmoSlaSupports::is_mesh_update_necessary() const
if (m_state != On || !m_model_object || m_model_object->instances.empty()) if (m_state != On || !m_model_object || m_model_object->instances.empty())
return false; return false;
if ((m_model_object->instances.front()->get_matrix() * m_source_data.matrix.inverse() * Vec3d(1., 1., 1.) - Vec3d(1., 1., 1.)).norm() > 0.001) if ((m_instance_matrix * m_source_data.matrix.inverse() * Vec3d(1., 1., 1.) - Vec3d(1., 1., 1.)).norm() > 0.001)
return true; return true;
// following should detect direct mesh changes (can be removed after the mesh is made completely immutable): // following should detect direct mesh changes (can be removed after the mesh is made completely immutable):
@ -1726,7 +1731,7 @@ void GLGizmoSlaSupports::update_mesh()
{ {
Eigen::MatrixXf& V = m_V; Eigen::MatrixXf& V = m_V;
Eigen::MatrixXi& F = m_F; Eigen::MatrixXi& F = m_F;
TriangleMesh mesh(m_model_object->mesh()); TriangleMesh mesh = m_model_object->mesh();
const stl_file& stl = mesh.stl; const stl_file& stl = mesh.stl;
V.resize(3 * stl.stats.number_of_facets, 3); V.resize(3 * stl.stats.number_of_facets, 3);
F.resize(stl.stats.number_of_facets, 3); F.resize(stl.stats.number_of_facets, 3);
@ -1739,15 +1744,19 @@ void GLGizmoSlaSupports::update_mesh()
F(i, 1) = 3*i+1; F(i, 1) = 3*i+1;
F(i, 2) = 3*i+2; F(i, 2) = 3*i+2;
} }
m_source_data.matrix = m_model_object->instances.front()->get_matrix();
const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex(); m_AABB = igl::AABB<Eigen::MatrixXf,3>();
m_source_data.mesh_first_point = Vec3d((double)first_vertex[0], (double)first_vertex[1], (double)first_vertex[2]); m_AABB.init(m_V, m_F);
m_source_data.matrix = m_instance_matrix;
// we'll now reload Grabbers (selection might have changed): // we'll now reload Grabbers (selection might have changed):
m_grabbers.clear(); m_grabbers.clear();
for (const Vec3f& point : m_model_object->sla_support_points) { for (const Vec3f& point : m_model_object->sla_support_points) {
m_grabbers.push_back(Grabber()); m_grabbers.push_back(Grabber());
m_grabbers.back().center = point.cast<double>(); m_grabbers.back().center = point.cast<double>();
} }
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
@ -1763,24 +1772,21 @@ Vec3f GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos)
Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> projection_matrix; Eigen::Matrix<GLdouble, 4, 4, Eigen::DontAlign> projection_matrix;
::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data()); ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data());
int fid = 0; Vec3d point1;
Eigen::Vector3f bc(0, 0, 0); Vec3d point2;
if (!igl::unproject_onto_mesh(Vec2f(mouse_pos(0), viewport(3)-mouse_pos(1)), modelview_matrix.cast<float>(), projection_matrix.cast<float>(), viewport.cast<float>(), m_V, m_F, fid, bc)) ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2));
/*if (!igl::embree::unproject_onto_mesh(Vec2f(mouse_pos(0), viewport(3)-mouse_pos(1)), ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2));
m_F,
modelview_matrix.cast<float>(),
projection_matrix.cast<float>(),
viewport.cast<float>(),
m_intersector,
fid,
bc))*/
throw "unable to unproject_onto_mesh";
const Vec3f& a = m_V.row(m_F(fid, 0)); igl::Hit hit;
const Vec3f& b = m_V.row(m_F(fid, 1));
const Vec3f& c = m_V.row(m_F(fid, 2)); if (!m_AABB.intersect_ray(m_V, m_F, point1.cast<float>(), (point2-point1).cast<float>(), hit))
Vec3f point = bc(0)*a + bc(1)*b + bc(2)*c; throw std::invalid_argument("unproject_on_mesh(): No intersection found.");
return m_model_object->instances.front()->get_matrix().inverse().cast<float>() * point;
int fid = hit.id;
Vec3f bc(1-hit.u-hit.v, hit.u, hit.v);
Vec3f point = bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2));
return m_instance_matrix.inverse().cast<float>() * point;
} }
void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position) void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position)
@ -1788,14 +1794,17 @@ void GLGizmoSlaSupports::clicked_on_object(const Vec2d& mouse_position)
Vec3f new_pos; Vec3f new_pos;
try { try {
new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new grabber in that case new_pos = unproject_on_mesh(mouse_position); // this can throw - we don't want to create a new grabber in that case
m_grabbers.push_back(Grabber());
m_grabbers.back().center = new_pos.cast<double>();
m_model_object->sla_support_points.push_back(new_pos);
// This should trigger the support generation
// wxGetApp().plater()->reslice();
} }
catch (...) {} catch (...) { return; }
m_grabbers.push_back(Grabber());
m_grabbers.back().center = new_pos.cast<double>();
m_model_object->sla_support_points.push_back(new_pos);
// This should trigger the support generation
// wxGetApp().plater()->reslice();
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
void GLGizmoSlaSupports::delete_current_grabber(bool delete_all) void GLGizmoSlaSupports::delete_current_grabber(bool delete_all)
@ -1816,6 +1825,8 @@ void GLGizmoSlaSupports::delete_current_grabber(bool delete_all)
// This should trigger the support generation // This should trigger the support generation
// wxGetApp().plater()->reslice(); // wxGetApp().plater()->reslice();
} }
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
void GLGizmoSlaSupports::on_update(const UpdateData& data) void GLGizmoSlaSupports::on_update(const UpdateData& data)
@ -1824,20 +1835,21 @@ void GLGizmoSlaSupports::on_update(const UpdateData& data)
Vec3f new_pos; Vec3f new_pos;
try { try {
new_pos = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1))); new_pos = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1)));
m_grabbers[m_hover_id].center = new_pos.cast<double>();
m_model_object->sla_support_points[m_hover_id] = new_pos;
} }
catch (...) {} catch (...) { return; }
m_grabbers[m_hover_id].center = new_pos.cast<double>();
m_model_object->sla_support_points[m_hover_id] = new_pos;
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
} }
void GLGizmoSlaSupports::render_tooltip_texture() const { void GLGizmoSlaSupports::render_tooltip_texture() const {
if (m_tooltip_texture.get_id() == 0) if (m_tooltip_texture.get_id() == 0)
if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/variable_layer_height_tooltip.png", false)) if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/sla_support_points_tooltip.png", false))
return; return;
if (m_reset_texture.get_id() == 0) if (m_reset_texture.get_id() == 0)
if (!m_reset_texture.load_from_file(resources_dir() + "/icons/variable_layer_height_reset.png", false)) if (!m_reset_texture.load_from_file(resources_dir() + "/icons/sla_support_points_reset.png", false))
return; return;
float zoom = m_parent.get_camera_zoom(); float zoom = m_parent.get_camera_zoom();
@ -1863,7 +1875,8 @@ void GLGizmoSlaSupports::render_tooltip_texture() const {
bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const
{ {
return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA); return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA)
&& selection.is_from_single_instance();
} }
bool GLGizmoSlaSupports::on_is_selectable() const bool GLGizmoSlaSupports::on_is_selectable() const

View File

@ -1,6 +1,8 @@
#ifndef slic3r_GLGizmo_hpp_ #ifndef slic3r_GLGizmo_hpp_
#define slic3r_GLGizmo_hpp_ #define slic3r_GLGizmo_hpp_
#include <igl/AABB.h>
#include "../../slic3r/GUI/GLTexture.hpp" #include "../../slic3r/GUI/GLTexture.hpp"
#include "../../slic3r/GUI/GLCanvas3D.hpp" #include "../../slic3r/GUI/GLCanvas3D.hpp"
#include "../../libslic3r/Point.hpp" #include "../../libslic3r/Point.hpp"
@ -449,11 +451,13 @@ class GLGizmoSlaSupports : public GLGizmoBase
{ {
private: private:
ModelObject* m_model_object = nullptr; ModelObject* m_model_object = nullptr;
Transform3d m_model_object_matrix; Transform3d m_instance_matrix;
Vec3f unproject_on_mesh(const Vec2d& mouse_pos); Vec3f unproject_on_mesh(const Vec2d& mouse_pos);
Eigen::MatrixXf m_V; // vertices Eigen::MatrixXf m_V; // vertices
Eigen::MatrixXi m_F; // facets indices Eigen::MatrixXi m_F; // facets indices
igl::AABB<Eigen::MatrixXf,3> m_AABB;
struct SourceDataSummary { struct SourceDataSummary {
BoundingBoxf3 bounding_box; BoundingBoxf3 bounding_box;
Transform3d matrix; Transform3d matrix;