Hollowing task triggered by the gizmo now spawns a UI job to not block the UI thread
The AABB tree calculation is still done in the UI thread, so it gets blocked for some time
This commit is contained in:
parent
4d8631fef6
commit
9836533cb3
@ -5,19 +5,13 @@
|
|||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
//#include <wx/msgdlg.h>
|
|
||||||
//#include <wx/settings.h>
|
|
||||||
//#include <wx/stattext.h>
|
|
||||||
|
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
|
||||||
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
#include "slic3r/GUI/MeshUtils.hpp"
|
#include "slic3r/GUI/MeshUtils.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#include "slic3r/GUI/PresetBundle.hpp"
|
#include "slic3r/GUI/PresetBundle.hpp"
|
||||||
#include "libslic3r/SLAPrint.hpp"
|
#include "libslic3r/SLAPrint.hpp"
|
||||||
#include "libslic3r/OpenVDBUtils.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -26,7 +20,6 @@ namespace GUI {
|
|||||||
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
, m_quadric(nullptr)
|
, m_quadric(nullptr)
|
||||||
, m_its(nullptr)
|
|
||||||
{
|
{
|
||||||
m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||||
m_quadric = ::gluNewQuadric();
|
m_quadric = ::gluNewQuadric();
|
||||||
@ -48,8 +41,8 @@ bool GLGizmoHollow::on_init()
|
|||||||
|
|
||||||
m_desc["head_diameter"] = _(L("Head diameter")) + ": ";
|
m_desc["head_diameter"] = _(L("Head diameter")) + ": ";
|
||||||
m_desc["lock_supports"] = _(L("Lock supports under new islands"));
|
m_desc["lock_supports"] = _(L("Lock supports under new islands"));
|
||||||
m_desc["remove_selected"] = _(L("Remove selected points"));
|
m_desc["remove_selected"] = _(L("Remove selected holes"));
|
||||||
m_desc["remove_all"] = _(L("Remove all points"));
|
m_desc["remove_all"] = _(L("Remove all holes"));
|
||||||
m_desc["apply_changes"] = _(L("Apply changes"));
|
m_desc["apply_changes"] = _(L("Apply changes"));
|
||||||
m_desc["discard_changes"] = _(L("Discard changes"));
|
m_desc["discard_changes"] = _(L("Discard changes"));
|
||||||
m_desc["minimal_distance"] = _(L("Minimal points distance")) + ": ";
|
m_desc["minimal_distance"] = _(L("Minimal points distance")) + ": ";
|
||||||
@ -113,7 +106,7 @@ void GLGizmoHollow::on_render() const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! m_its || ! m_mesh)
|
if (! m_mesh)
|
||||||
const_cast<GLGizmoHollow*>(this)->update_mesh();
|
const_cast<GLGizmoHollow*>(this)->update_mesh();
|
||||||
|
|
||||||
if (m_volume_with_cavity) {
|
if (m_volume_with_cavity) {
|
||||||
@ -212,7 +205,7 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const
|
|||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_supports_clipper && ! m_supports_clipper->get_triangles().empty() && !m_editing_mode) {
|
if (m_supports_clipper && ! m_supports_clipper->get_triangles().empty()) {
|
||||||
// The supports are hidden in the editing mode, so it makes no sense to render the cuts.
|
// The supports are hidden in the editing mode, so it makes no sense to render the cuts.
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glColor3f(1.0f, 0.f, 0.37f);
|
::glColor3f(1.0f, 0.f, 0.37f);
|
||||||
@ -310,12 +303,14 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
//const double cone_rad_diff = m_new_cone_angle*(cone_radius/(cone_height/2.))*(cone_height/2.);
|
//const double cone_rad_diff = m_new_cone_angle*(cone_radius/(cone_height/2.))*(cone_height/2.);
|
||||||
const double cone_rad_diff = m_new_cone_angle*cone_radius;
|
const double cone_rad_diff = m_new_cone_angle*cone_radius;
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslatef(0.f, 0.f, -cone_height/2.));
|
glsafe(::glTranslated(0., 0., -cone_height/2.));
|
||||||
//::gluCylinder(m_quadric, cone_radius, cone_radius, cone_height, 24, 1);
|
//::gluCylinder(m_quadric, cone_radius, cone_radius, cone_height, 24, 1);
|
||||||
::gluCylinder(m_quadric, cone_radius+cone_rad_diff, cone_radius-cone_rad_diff, cone_height, 24, 1);
|
::gluCylinder(m_quadric, cone_radius+cone_rad_diff, cone_radius-cone_rad_diff, cone_height, 24, 1);
|
||||||
glsafe(::glTranslatef(0.f, 0.f, cone_height));
|
glsafe(::glTranslated(0., 0., cone_height));
|
||||||
//::gluDisk(m_quadric, 0.0, cone_radius, 24, 1);
|
|
||||||
::gluDisk(m_quadric, 0.0, cone_radius-cone_rad_diff, 24, 1);
|
::gluDisk(m_quadric, 0.0, cone_radius-cone_rad_diff, 24, 1);
|
||||||
|
glsafe(::glTranslated(0., 0., -cone_height));
|
||||||
|
glsafe(::glRotatef(180.f, 1.f, 0.f, 0.f));
|
||||||
|
::gluDisk(m_quadric, 0.0, cone_radius+cone_rad_diff, 24, 1);
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
}
|
}
|
||||||
//::gluSphere(m_quadric, (double)support_point.head_front_radius * RenderPointScale, 24, 12);
|
//::gluSphere(m_quadric, (double)support_point.head_front_radius * RenderPointScale, 24, 12);
|
||||||
@ -354,7 +349,7 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
|
|||||||
bool GLGizmoHollow::is_mesh_update_necessary() const
|
bool GLGizmoHollow::is_mesh_update_necessary() const
|
||||||
{
|
{
|
||||||
return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty())
|
return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty())
|
||||||
&& ((m_model_object->id() != m_model_object_id) || m_its == nullptr);
|
&& ((m_model_object->id() != m_model_object_id) || ! m_mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -368,7 +363,6 @@ void GLGizmoHollow::update_mesh()
|
|||||||
// this way we can use that mesh directly.
|
// this way we can use that mesh directly.
|
||||||
// This mesh does not account for the possible Z up SLA offset.
|
// This mesh does not account for the possible Z up SLA offset.
|
||||||
m_mesh = &m_model_object->volumes.front()->mesh();
|
m_mesh = &m_model_object->volumes.front()->mesh();
|
||||||
m_its = &m_mesh->its;
|
|
||||||
|
|
||||||
// If this is different mesh than last time
|
// If this is different mesh than last time
|
||||||
if (m_model_object_id != m_model_object->id()) {
|
if (m_model_object_id != m_model_object->id()) {
|
||||||
@ -449,7 +443,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||||||
if (m_selection_empty) {
|
if (m_selection_empty) {
|
||||||
std::pair<Vec3f, Vec3f> pos_and_normal;
|
std::pair<Vec3f, Vec3f> pos_and_normal;
|
||||||
if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection
|
if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add support point")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add drainage hole")));
|
||||||
m_editing_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second);
|
m_editing_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second);
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
m_wait_for_up_event = true;
|
m_wait_for_up_event = true;
|
||||||
@ -563,7 +557,7 @@ void GLGizmoHollow::delete_selected_points(bool force)
|
|||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Delete support point")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Delete drainage hole")));
|
||||||
|
|
||||||
for (unsigned int idx=0; idx<m_editing_cache.size(); ++idx) {
|
for (unsigned int idx=0; idx<m_editing_cache.size(); ++idx) {
|
||||||
if (m_editing_cache[idx].selected) {
|
if (m_editing_cache[idx].selected) {
|
||||||
@ -594,30 +588,38 @@ void GLGizmoHollow::on_update(const UpdateData& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoHollow::get_hollowing_parameters(TriangleMesh const** object_mesh, float& offset, float& adaptability) const
|
||||||
void GLGizmoHollow::hollow_mesh(float offset, float adaptibility)
|
|
||||||
{
|
{
|
||||||
Slic3r::sla::Contour3D imesh{*m_mesh};
|
offset = m_offset;
|
||||||
auto ptr = meshToVolume(imesh, {});
|
adaptability = m_adaptability;
|
||||||
sla::Contour3D omesh = volumeToMesh(*ptr, -offset, adaptibility, true);
|
*object_mesh = m_mesh;
|
||||||
|
}
|
||||||
|
|
||||||
if (omesh.empty())
|
void GLGizmoHollow::hollow_mesh()
|
||||||
return;
|
{
|
||||||
|
// Trigger a UI job to hollow the mesh.
|
||||||
|
wxGetApp().plater()->hollow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr<TriangleMesh> mesh)
|
||||||
|
{
|
||||||
|
// Called from Plater when the UI job finishes
|
||||||
|
m_cavity_mesh = std::move(mesh);
|
||||||
|
|
||||||
imesh.merge(omesh);
|
|
||||||
m_cavity_mesh.reset(new TriangleMesh);
|
|
||||||
*m_cavity_mesh = sla::to_triangle_mesh(imesh);
|
|
||||||
m_cavity_mesh.get()->require_shared_vertices();
|
|
||||||
m_mesh_raycaster.reset(new MeshRaycaster(*m_cavity_mesh.get()));
|
m_mesh_raycaster.reset(new MeshRaycaster(*m_cavity_mesh.get()));
|
||||||
m_object_clipper.reset();
|
m_object_clipper.reset();
|
||||||
|
m_volume_with_cavity.reset();
|
||||||
|
|
||||||
// create a new GLVolume that only has the cavity inside
|
if(m_cavity_mesh) {// create a new GLVolume that only has the cavity inside
|
||||||
m_volume_with_cavity.reset(new GLVolume(1.f, 0.f, 0.f, 0.5f));
|
Geometry::Transformation volume_trafo = m_model_object->volumes.front()->get_transformation();
|
||||||
m_volume_with_cavity->indexed_vertex_array.load_mesh(*m_cavity_mesh.get());
|
volume_trafo.set_offset(volume_trafo.get_offset() + Vec3d(0., 0., m_z_shift));
|
||||||
m_volume_with_cavity->finalize_geometry(true);
|
m_volume_with_cavity.reset(new GLVolume(1.f, 0.f, 0.f, 0.5f));
|
||||||
m_volume_with_cavity->set_volume_transformation(m_model_object->volumes.front()->get_transformation());
|
m_volume_with_cavity->indexed_vertex_array.load_mesh(*m_cavity_mesh.get());
|
||||||
m_volume_with_cavity->set_instance_transformation(m_model_object->instances[m_active_instance]->get_transformation());
|
m_volume_with_cavity->finalize_geometry(true);
|
||||||
m_parent.toggle_model_objects_visibility(false, m_model_object, m_active_instance);
|
m_volume_with_cavity->set_volume_transformation(volume_trafo);
|
||||||
|
m_volume_with_cavity->set_instance_transformation(m_model_object->instances[m_active_instance]->get_transformation());
|
||||||
|
}
|
||||||
|
m_parent.toggle_model_objects_visibility(! m_cavity_mesh, m_model_object, m_active_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const ConfigOption*> GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
|
std::vector<const ConfigOption*> GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
|
||||||
@ -695,9 +697,8 @@ RENDER_AGAIN:
|
|||||||
|
|
||||||
if (m_editing_mode) {
|
if (m_editing_mode) {
|
||||||
|
|
||||||
if (m_imgui->button(m_desc.at("hollow"))) {
|
if (m_imgui->button(m_desc.at("hollow")))
|
||||||
hollow_mesh(m_offset, m_adaptibility);
|
hollow_mesh();
|
||||||
}
|
|
||||||
|
|
||||||
float diameter_upper_cap = static_cast<ConfigOptionFloat*>(wxGetApp().preset_bundle->sla_prints.get_edited_preset().config.option("support_pillar_diameter"))->value;
|
float diameter_upper_cap = static_cast<ConfigOptionFloat*>(wxGetApp().preset_bundle->sla_prints.get_edited_preset().config.option("support_pillar_diameter"))->value;
|
||||||
if (m_new_point_head_diameter > diameter_upper_cap)
|
if (m_new_point_head_diameter > diameter_upper_cap)
|
||||||
@ -728,7 +729,7 @@ RENDER_AGAIN:
|
|||||||
cache_entry.support_point.head_front_radius = m_old_point_head_diameter / 2.f;
|
cache_entry.support_point.head_front_radius = m_old_point_head_diameter / 2.f;
|
||||||
float backup = m_new_point_head_diameter;
|
float backup = m_new_point_head_diameter;
|
||||||
m_new_point_head_diameter = m_old_point_head_diameter;
|
m_new_point_head_diameter = m_old_point_head_diameter;
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Change point head diameter")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Change drainage hole diameter")));
|
||||||
m_new_point_head_diameter = backup;
|
m_new_point_head_diameter = backup;
|
||||||
for (auto& cache_entry : m_editing_cache)
|
for (auto& cache_entry : m_editing_cache)
|
||||||
if (cache_entry.selected)
|
if (cache_entry.selected)
|
||||||
@ -757,10 +758,10 @@ RENDER_AGAIN:
|
|||||||
|
|
||||||
m_imgui->text("Offset: ");
|
m_imgui->text("Offset: ");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SliderFloat(" ", &m_offset, 0.f, 10.f, "%.1f");
|
ImGui::SliderFloat(" ", &m_offset, 0.f, 5.f, "%.1f");
|
||||||
m_imgui->text("Adaptibility: ");
|
m_imgui->text("Adaptibility: ");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SliderFloat(" ", &m_adaptibility, 0.f, 1.f, "%.1f");
|
ImGui::SliderFloat(" ", &m_adaptability, 0.f, 1.f, "%.1f");
|
||||||
}
|
}
|
||||||
else { // not in editing mode:
|
else { // not in editing mode:
|
||||||
m_imgui->text(m_desc.at("minimal_distance"));
|
m_imgui->text(m_desc.at("minimal_distance"));
|
||||||
@ -912,7 +913,7 @@ void GLGizmoHollow::on_set_state()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
|
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
|
//Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
|
||||||
if (is_mesh_update_necessary())
|
if (is_mesh_update_necessary())
|
||||||
update_mesh();
|
update_mesh();
|
||||||
|
|
||||||
@ -929,27 +930,16 @@ void GLGizmoHollow::on_set_state()
|
|||||||
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
|
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
|
||||||
}
|
}
|
||||||
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
|
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
|
||||||
bool will_ask = m_model_object && false;
|
//Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off")));
|
||||||
if (will_ask) {
|
m_parent.toggle_model_objects_visibility(true);
|
||||||
wxGetApp().CallAfter([this]() {
|
m_normal_cache.clear();
|
||||||
});
|
m_clipping_plane_distance = 0.f;
|
||||||
// refuse to be turned off so the gizmo is active when the CallAfter is executed
|
// Release clippers and the AABB raycaster.
|
||||||
m_state = m_old_state;
|
m_object_clipper.reset();
|
||||||
}
|
m_supports_clipper.reset();
|
||||||
else {
|
m_mesh_raycaster.reset();
|
||||||
// we are actually shutting down
|
m_cavity_mesh.reset();
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off")));
|
m_volume_with_cavity.reset();
|
||||||
m_parent.toggle_model_objects_visibility(true);
|
|
||||||
m_normal_cache.clear();
|
|
||||||
m_clipping_plane_distance = 0.f;
|
|
||||||
// Release clippers and the AABB raycaster.
|
|
||||||
m_its = nullptr;
|
|
||||||
m_object_clipper.reset();
|
|
||||||
m_supports_clipper.reset();
|
|
||||||
m_mesh_raycaster.reset();
|
|
||||||
m_cavity_mesh.reset();
|
|
||||||
m_volume_with_cavity.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_old_state = m_state;
|
m_old_state = m_state;
|
||||||
}
|
}
|
||||||
@ -977,7 +967,7 @@ void GLGizmoHollow::on_stop_dragging()
|
|||||||
&& backup.support_point.pos != m_point_before_drag.support_point.pos) // and it was moved, not just selected
|
&& backup.support_point.pos != m_point_before_drag.support_point.pos) // and it was moved, not just selected
|
||||||
{
|
{
|
||||||
m_editing_cache[m_hover_id] = m_point_before_drag;
|
m_editing_cache[m_hover_id] = m_point_before_drag;
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Move support point")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Move drainage hole")));
|
||||||
m_editing_cache[m_hover_id] = backup;
|
m_editing_cache[m_hover_id] = backup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ private:
|
|||||||
std::unique_ptr<TriangleMesh> m_cavity_mesh;
|
std::unique_ptr<TriangleMesh> m_cavity_mesh;
|
||||||
std::unique_ptr<GLVolume> m_volume_with_cavity;
|
std::unique_ptr<GLVolume> m_volume_with_cavity;
|
||||||
const TriangleMesh* m_mesh;
|
const TriangleMesh* m_mesh;
|
||||||
const indexed_triangle_set* m_its;
|
|
||||||
mutable const TriangleMesh* m_supports_mesh;
|
mutable const TriangleMesh* m_supports_mesh;
|
||||||
mutable std::vector<Vec2f> m_triangles;
|
mutable std::vector<Vec2f> m_triangles;
|
||||||
mutable std::vector<Vec2f> m_supports_triangles;
|
mutable std::vector<Vec2f> m_supports_triangles;
|
||||||
@ -78,6 +77,8 @@ public:
|
|||||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||||
void delete_selected_points(bool force = false);
|
void delete_selected_points(bool force = false);
|
||||||
ClippingPlane get_sla_clipping_plane() const;
|
ClippingPlane get_sla_clipping_plane() const;
|
||||||
|
void update_hollowed_mesh(std::unique_ptr<TriangleMesh> mesh);
|
||||||
|
void get_hollowing_parameters(TriangleMesh const** object_mesh, float& offset, float& adaptability) const;
|
||||||
|
|
||||||
bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); }
|
bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); }
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ private:
|
|||||||
void render_clipping_plane(const Selection& selection) const;
|
void render_clipping_plane(const Selection& selection) const;
|
||||||
bool is_mesh_update_necessary() const;
|
bool is_mesh_update_necessary() const;
|
||||||
void update_mesh();
|
void update_mesh();
|
||||||
void hollow_mesh(float offset = 2.f, float adaptability = 1.f);
|
void hollow_mesh();
|
||||||
bool unsaved_changes() const;
|
bool unsaved_changes() const;
|
||||||
const TriangleMesh* mesh() const;
|
const TriangleMesh* mesh() const;
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ private:
|
|||||||
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
||||||
|
|
||||||
float m_offset = 2.f;
|
float m_offset = 2.f;
|
||||||
float m_adaptibility = 1.f;
|
float m_adaptability = 1.f;
|
||||||
|
|
||||||
float m_clipping_plane_distance = 0.f;
|
float m_clipping_plane_distance = 0.f;
|
||||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||||
|
@ -158,6 +158,7 @@ public:
|
|||||||
void update_data();
|
void update_data();
|
||||||
|
|
||||||
EType get_current_type() const { return m_current; }
|
EType get_current_type() const { return m_current; }
|
||||||
|
GLGizmoBase* get_current() const;
|
||||||
|
|
||||||
bool is_running() const;
|
bool is_running() const;
|
||||||
bool handle_shortcut(int key);
|
bool handle_shortcut(int key);
|
||||||
@ -206,8 +207,6 @@ private:
|
|||||||
float get_total_overlay_height() const;
|
float get_total_overlay_height() const;
|
||||||
float get_total_overlay_width() const;
|
float get_total_overlay_width() const;
|
||||||
|
|
||||||
GLGizmoBase* get_current() const;
|
|
||||||
|
|
||||||
bool generate_icons_texture() const;
|
bool generate_icons_texture() const;
|
||||||
|
|
||||||
void update_on_off_state(const Vec2d& mouse_pos);
|
void update_on_off_state(const Vec2d& mouse_pos);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "libslic3r/Format/3mf.hpp"
|
#include "libslic3r/Format/3mf.hpp"
|
||||||
#include "libslic3r/GCode/PreviewData.hpp"
|
#include "libslic3r/GCode/PreviewData.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
|
#include "libslic3r/OpenVDBUtils.hpp"
|
||||||
#include "libslic3r/Polygon.hpp"
|
#include "libslic3r/Polygon.hpp"
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
@ -1559,7 +1560,8 @@ struct Plater::priv
|
|||||||
|
|
||||||
enum class Jobs : size_t {
|
enum class Jobs : size_t {
|
||||||
Arrange,
|
Arrange,
|
||||||
Rotoptimize
|
Rotoptimize,
|
||||||
|
Hollow
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArrangeJob : public Job
|
class ArrangeJob : public Job
|
||||||
@ -1703,6 +1705,20 @@ struct Plater::priv
|
|||||||
void process() override;
|
void process() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HollowJob : public Job
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Job::Job;
|
||||||
|
void prepare() override;
|
||||||
|
void process() override;
|
||||||
|
void finalize() override;
|
||||||
|
private:
|
||||||
|
std::unique_ptr<TriangleMesh> m_output;
|
||||||
|
const TriangleMesh* m_object_mesh = nullptr;
|
||||||
|
float m_offset = 0.f;
|
||||||
|
float m_adaptability = 0.f;
|
||||||
|
};
|
||||||
|
|
||||||
// Jobs defined inside the group class will be managed so that only one can
|
// Jobs defined inside the group class will be managed so that only one can
|
||||||
// run at a time. Also, the background process will be stopped if a job is
|
// run at a time. Also, the background process will be stopped if a job is
|
||||||
// started.
|
// started.
|
||||||
@ -1714,6 +1730,7 @@ struct Plater::priv
|
|||||||
|
|
||||||
ArrangeJob arrange_job{m_plater};
|
ArrangeJob arrange_job{m_plater};
|
||||||
RotoptimizeJob rotoptimize_job{m_plater};
|
RotoptimizeJob rotoptimize_job{m_plater};
|
||||||
|
HollowJob hollow_job{m_plater};
|
||||||
|
|
||||||
// To create a new job, just define a new subclass of Job, implement
|
// To create a new job, just define a new subclass of Job, implement
|
||||||
// the process and the optional prepare() and finalize() methods
|
// the process and the optional prepare() and finalize() methods
|
||||||
@ -1721,7 +1738,8 @@ struct Plater::priv
|
|||||||
// if it cannot run concurrently with other jobs in this group
|
// if it cannot run concurrently with other jobs in this group
|
||||||
|
|
||||||
std::vector<std::reference_wrapper<Job>> m_jobs{arrange_job,
|
std::vector<std::reference_wrapper<Job>> m_jobs{arrange_job,
|
||||||
rotoptimize_job};
|
rotoptimize_job,
|
||||||
|
hollow_job};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ExclusiveJobGroup(priv *_plater) : m_plater(_plater) {}
|
ExclusiveJobGroup(priv *_plater) : m_plater(_plater) {}
|
||||||
@ -1816,6 +1834,7 @@ struct Plater::priv
|
|||||||
void reset();
|
void reset();
|
||||||
void mirror(Axis axis);
|
void mirror(Axis axis);
|
||||||
void arrange();
|
void arrange();
|
||||||
|
void hollow();
|
||||||
void sla_optimize_rotation();
|
void sla_optimize_rotation();
|
||||||
void split_object();
|
void split_object();
|
||||||
void split_volume();
|
void split_volume();
|
||||||
@ -2703,6 +2722,12 @@ void Plater::priv::arrange()
|
|||||||
m_ui_jobs.start(Jobs::Arrange);
|
m_ui_jobs.start(Jobs::Arrange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::priv::hollow()
|
||||||
|
{
|
||||||
|
this->take_snapshot(_(L("Hollow")));
|
||||||
|
m_ui_jobs.start(Jobs::Hollow);
|
||||||
|
}
|
||||||
|
|
||||||
// This method will find an optimal orientation for the currently selected item
|
// This method will find an optimal orientation for the currently selected item
|
||||||
// Very similar in nature to the arrange method above...
|
// Very similar in nature to the arrange method above...
|
||||||
void Plater::priv::sla_optimize_rotation() {
|
void Plater::priv::sla_optimize_rotation() {
|
||||||
@ -2834,6 +2859,38 @@ void Plater::priv::RotoptimizeJob::process()
|
|||||||
: _(L("Orientation found.")));
|
: _(L("Orientation found.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::priv::HollowJob::prepare()
|
||||||
|
{
|
||||||
|
const GLGizmosManager& gizmo_manager = plater().q->canvas3D()->get_gizmos_manager();
|
||||||
|
const GLGizmoHollow* gizmo_hollow = dynamic_cast<const GLGizmoHollow*>(gizmo_manager.get_current());
|
||||||
|
assert(gizmo_hollow);
|
||||||
|
gizmo_hollow->get_hollowing_parameters(&m_object_mesh, m_offset, m_adaptability);
|
||||||
|
m_output.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::HollowJob::process()
|
||||||
|
{
|
||||||
|
Slic3r::sla::Contour3D imesh{*m_object_mesh};
|
||||||
|
auto ptr = meshToVolume(imesh, {});
|
||||||
|
sla::Contour3D omesh = volumeToMesh(*ptr, -m_offset, m_adaptability, true);
|
||||||
|
|
||||||
|
if (omesh.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
imesh.merge(omesh);
|
||||||
|
m_output.reset(new TriangleMesh());
|
||||||
|
*m_output = sla::to_triangle_mesh(imesh);
|
||||||
|
m_output->require_shared_vertices();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::HollowJob::finalize()
|
||||||
|
{
|
||||||
|
const GLGizmosManager& gizmo_manager = plater().q->canvas3D()->get_gizmos_manager();
|
||||||
|
GLGizmoHollow* gizmo_hollow = dynamic_cast<GLGizmoHollow*>(gizmo_manager.get_current());
|
||||||
|
assert(gizmo_hollow);
|
||||||
|
gizmo_hollow->update_hollowed_mesh(std::move(m_output));
|
||||||
|
}
|
||||||
|
|
||||||
void Plater::priv::split_object()
|
void Plater::priv::split_object()
|
||||||
{
|
{
|
||||||
int obj_idx = get_selected_object_idx();
|
int obj_idx = get_selected_object_idx();
|
||||||
@ -4661,6 +4718,11 @@ void Plater::export_toolpaths_to_obj() const
|
|||||||
p->preview->get_canvas3d()->export_toolpaths_to_obj(into_u8(path).c_str());
|
p->preview->get_canvas3d()->export_toolpaths_to_obj(into_u8(path).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::hollow()
|
||||||
|
{
|
||||||
|
p->hollow();
|
||||||
|
}
|
||||||
|
|
||||||
void Plater::reslice()
|
void Plater::reslice()
|
||||||
{
|
{
|
||||||
// Stop arrange and (or) optimize rotation tasks.
|
// Stop arrange and (or) optimize rotation tasks.
|
||||||
|
@ -190,6 +190,7 @@ public:
|
|||||||
void reload_from_disk();
|
void reload_from_disk();
|
||||||
bool has_toolpaths_to_export() const;
|
bool has_toolpaths_to_export() const;
|
||||||
void export_toolpaths_to_obj() const;
|
void export_toolpaths_to_obj() const;
|
||||||
|
void hollow();
|
||||||
void reslice();
|
void reslice();
|
||||||
void reslice_SLA_supports(const ModelObject &object, bool postpone_error_messages = false);
|
void reslice_SLA_supports(const ModelObject &object, bool postpone_error_messages = false);
|
||||||
void changed_object(int obj_idx);
|
void changed_object(int obj_idx);
|
||||||
|
Loading…
Reference in New Issue
Block a user