diff options
Diffstat (limited to 'src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp')
-rw-r--r-- | src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 112 |
1 files changed, 55 insertions, 57 deletions
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 9fae8893a..fc5edff6d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -1,7 +1,9 @@ // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. #include "GLGizmoFlatten.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" -#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" + +#include "libslic3r/Model.hpp" #include <numeric> @@ -26,23 +28,16 @@ bool GLGizmoFlatten::on_init() void GLGizmoFlatten::on_set_state() { - // m_model_object pointer can be invalid (for instance because of undo/redo action), - // we should recover it from the object id - m_model_object = nullptr; - for (const auto mo : wxGetApp().model().objects) { - if (mo->id() == m_model_object_id) { - m_model_object = mo; - break; - } - } +} - if (m_state == On && is_plane_update_necessary()) - update_planes(); +CommonGizmosDataID GLGizmoFlatten::on_get_requirements() const +{ + return CommonGizmosDataID::SelectionInfo; } std::string GLGizmoFlatten::on_get_name() const { - return (_(L("Place on face")) + " [F]").ToUTF8().data(); + return (_L("Place on face") + " [F]").ToUTF8().data(); } bool GLGizmoFlatten::on_is_activable() const @@ -52,8 +47,7 @@ bool GLGizmoFlatten::on_is_activable() const void GLGizmoFlatten::on_start_dragging() { - if (m_hover_id != -1) - { + if (m_hover_id != -1) { assert(m_planes_valid); m_normal = m_planes[m_hover_id].normal; m_starting_center = m_parent.get_selection().get_bounding_box().center(); @@ -69,27 +63,21 @@ void GLGizmoFlatten::on_render() const glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_BLEND)); - if (selection.is_single_full_instance()) - { + if (selection.is_single_full_instance()) { const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); glsafe(::glPushMatrix()); glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z())); glsafe(::glMultMatrixd(m.data())); if (this->is_plane_update_necessary()) const_cast<GLGizmoFlatten*>(this)->update_planes(); - for (int i = 0; i < (int)m_planes.size(); ++i) - { + for (int i = 0; i < (int)m_planes.size(); ++i) { if (i == m_hover_id) glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.75f)); else glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.5f)); - ::glBegin(GL_POLYGON); - for (const Vec3d& vertex : m_planes[i].vertices) - { - ::glVertex3dv(vertex.data()); - } - glsafe(::glEnd()); + if (m_planes[i].vbo.has_VBOs()) + m_planes[i].vbo.render(); } glsafe(::glPopMatrix()); } @@ -105,23 +93,16 @@ void GLGizmoFlatten::on_render_for_picking() const glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_BLEND)); - if (selection.is_single_full_instance()) - { + if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) { const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); glsafe(::glPushMatrix()); glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z())); glsafe(::glMultMatrixd(m.data())); if (this->is_plane_update_necessary()) const_cast<GLGizmoFlatten*>(this)->update_planes(); - for (int i = 0; i < (int)m_planes.size(); ++i) - { + for (int i = 0; i < (int)m_planes.size(); ++i) { glsafe(::glColor4fv(picking_color_component(i).data())); - ::glBegin(GL_POLYGON); - for (const Vec3d& vertex : m_planes[i].vertices) - { - ::glVertex3dv(vertex.data()); - } - glsafe(::glEnd()); + m_planes[i].vbo.render(); } glsafe(::glPopMatrix()); } @@ -132,19 +113,17 @@ void GLGizmoFlatten::on_render_for_picking() const void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { m_starting_center = Vec3d::Zero(); - if (m_model_object != model_object) { + if (model_object != m_old_model_object) { m_planes.clear(); m_planes_valid = false; } - m_model_object = model_object; - m_model_object_id = model_object ? model_object->id() : 0; } void GLGizmoFlatten::update_planes() { + const ModelObject* mo = m_c->selection_info()->model_object(); TriangleMesh ch; - for (const ModelVolume* vol : m_model_object->volumes) - { + for (const ModelVolume* vol : mo->volumes) { if (vol->type() != ModelVolumeType::MODEL_PART) continue; TriangleMesh vol_ch = vol->get_convex_hull(); @@ -153,7 +132,7 @@ void GLGizmoFlatten::update_planes() } ch = ch.convex_hull_3d(); m_planes.clear(); - const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix(true); + const Transform3d& inst_matrix = mo->instances.front()->get_matrix(true); // Following constants are used for discarding too small polygons. const float minimal_area = 5.f; // in square mm (world coordinates) @@ -186,7 +165,7 @@ void GLGizmoFlatten::update_planes() if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) { stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex; for (int j=0; j<3; ++j) - m_planes.back().vertices.emplace_back((double)first_vertex[j](0), (double)first_vertex[j](1), (double)first_vertex[j](2)); + m_planes.back().vertices.emplace_back(first_vertex[j].cast<double>()); facet_visited[facet_idx] = true; for (int j = 0; j < 3; ++ j) { @@ -198,15 +177,16 @@ void GLGizmoFlatten::update_planes() } m_planes.back().normal = normal_ptr->cast<double>(); + Pointf3s& verts = m_planes.back().vertices; // Now we'll transform all the points into world coordinates, so that the areas, angles and distances // make real sense. - m_planes.back().vertices = transform(m_planes.back().vertices, inst_matrix); + verts = transform(verts, inst_matrix); // if this is a just a very small triangle, remove it to speed up further calculations (it would be rejected later anyway): - if (m_planes.back().vertices.size() == 3 && - ((m_planes.back().vertices[0] - m_planes.back().vertices[1]).norm() < minimal_side - || (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < minimal_side - || (m_planes.back().vertices[1] - m_planes.back().vertices[2]).norm() < minimal_side)) + if (verts.size() == 3 && + ((verts[0] - verts[1]).norm() < minimal_side + || (verts[0] - verts[2]).norm() < minimal_side + || (verts[1] - verts[2]).norm() < minimal_side)) m_planes.pop_back(); } @@ -331,12 +311,28 @@ void GLGizmoFlatten::update_planes() // Planes are finished - let's save what we calculated it from: m_volumes_matrices.clear(); m_volumes_types.clear(); - for (const ModelVolume* vol : m_model_object->volumes) { + for (const ModelVolume* vol : mo->volumes) { m_volumes_matrices.push_back(vol->get_matrix()); m_volumes_types.push_back(vol->type()); } - m_first_instance_scale = m_model_object->instances.front()->get_scaling_factor(); - m_first_instance_mirror = m_model_object->instances.front()->get_mirror(); + m_first_instance_scale = mo->instances.front()->get_scaling_factor(); + m_first_instance_mirror = mo->instances.front()->get_mirror(); + m_old_model_object = mo; + + // And finally create respective VBOs. The polygon is convex with + // the vertices in order, so triangulation is trivial. + for (auto& plane : m_planes) { + plane.vbo.reserve(plane.vertices.size()); + for (const auto& vert : plane.vertices) + plane.vbo.push_geometry(vert, plane.normal); + for (size_t i=1; i<plane.vertices.size()-1; ++i) + plane.vbo.push_triangle(0, i, i+1); // triangle fan + plane.vbo.finalize_geometry(true); + // FIXME: vertices should really be local, they need not + // persist now when we use VBOs + plane.vertices.clear(); + plane.vertices.shrink_to_fit(); + } m_planes_valid = true; } @@ -344,20 +340,22 @@ void GLGizmoFlatten::update_planes() bool GLGizmoFlatten::is_plane_update_necessary() const { - if (m_state != On || !m_model_object || m_model_object->instances.empty()) + const ModelObject* mo = m_c->selection_info()->model_object(); + if (m_state != On || ! mo || mo->instances.empty()) return false; - if (! m_planes_valid || m_model_object->volumes.size() != m_volumes_matrices.size()) + if (! m_planes_valid || mo != m_old_model_object + || mo->volumes.size() != m_volumes_matrices.size()) return true; // We want to recalculate when the scale changes - some planes could (dis)appear. - if (! m_model_object->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale) - || ! m_model_object->instances.front()->get_mirror().isApprox(m_first_instance_mirror)) + if (! mo->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale) + || ! mo->instances.front()->get_mirror().isApprox(m_first_instance_mirror)) return true; - for (unsigned int i=0; i < m_model_object->volumes.size(); ++i) - if (! m_model_object->volumes[i]->get_matrix().isApprox(m_volumes_matrices[i]) - || m_model_object->volumes[i]->type() != m_volumes_types[i]) + for (unsigned int i=0; i < mo->volumes.size(); ++i) + if (! mo->volumes[i]->get_matrix().isApprox(m_volumes_matrices[i]) + || mo->volumes[i]->type() != m_volumes_types[i]) return true; return false; |