Added simple autosetting of custom supports based on facet normal angle
This commit is contained in:
parent
e0b04e7d36
commit
d24a3453af
2 changed files with 150 additions and 76 deletions
src/slic3r/GUI/Gizmos
|
@ -523,6 +523,46 @@ void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool overwrite, bool block)
|
||||||
|
{
|
||||||
|
float threshold = (M_PI/180.)*threshold_deg;
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
const ModelInstance* mi = mo->instances[selection.get_instance_idx()];
|
||||||
|
|
||||||
|
int mesh_id = -1;
|
||||||
|
for (const ModelVolume* mv : mo->volumes) {
|
||||||
|
if (! mv->is_model_part())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
++mesh_id;
|
||||||
|
|
||||||
|
const Transform3d trafo_matrix = mi->get_matrix(true) * mv->get_matrix(true);
|
||||||
|
Vec3f down = (trafo_matrix.inverse() * (-Vec3d::UnitZ())).cast<float>().normalized();
|
||||||
|
Vec3f limit = (trafo_matrix.inverse() * Vec3d(std::sin(threshold), 0, -std::cos(threshold))).cast<float>().normalized();
|
||||||
|
|
||||||
|
float dot_limit = limit.dot(down);
|
||||||
|
|
||||||
|
// Now calculate dot product of vert_direction and facets' normals.
|
||||||
|
int idx = -1;
|
||||||
|
for (const stl_facet& facet : mv->mesh().stl.facet_start) {
|
||||||
|
++idx;
|
||||||
|
if (facet.normal.dot(down) > dot_limit && (overwrite || m_selected_facets[mesh_id][idx] == FacetSupportType::NONE))
|
||||||
|
m_selected_facets[mesh_id][idx] = block
|
||||||
|
? FacetSupportType::BLOCKER
|
||||||
|
: FacetSupportType::ENFORCER;
|
||||||
|
}
|
||||||
|
update_vertex_buffers(mv, mesh_id, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
||||||
|
: _L("Add supports by angle"));
|
||||||
|
update_model_object();
|
||||||
|
m_parent.set_as_dirty();
|
||||||
|
m_setting_angle = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_limit)
|
void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_limit)
|
||||||
{
|
{
|
||||||
if (! m_c->selection_info()->model_object())
|
if (! m_c->selection_info()->model_object())
|
||||||
|
@ -531,6 +571,8 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
const float approx_height = m_imgui->scaled(18.0f);
|
const float approx_height = m_imgui->scaled(18.0f);
|
||||||
y = std::min(y, bottom_limit - approx_height);
|
y = std::min(y, bottom_limit - approx_height);
|
||||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||||
|
|
||||||
|
if (! m_setting_angle) {
|
||||||
m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||||
|
|
||||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||||
|
@ -566,6 +608,12 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
|
|
||||||
m_imgui->text("");
|
m_imgui->text("");
|
||||||
|
|
||||||
|
if (m_imgui->button("Autoset by angle...")) {
|
||||||
|
m_setting_angle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (m_imgui->button(m_desc.at("remove_all"))) {
|
if (m_imgui->button(m_desc.at("remove_all"))) {
|
||||||
ModelObject* mo = m_c->selection_info()->model_object();
|
ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
|
@ -618,9 +666,29 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
m_imgui->end();
|
m_imgui->end();
|
||||||
|
if (m_setting_angle)
|
||||||
|
m_parent.set_as_dirty();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string name = "Autoset custom supports";
|
||||||
|
m_imgui->begin(wxString(name), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||||
|
m_imgui->text("Threshold:");
|
||||||
|
ImGui::SameLine();
|
||||||
|
m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, "%.f");
|
||||||
|
m_imgui->checkbox(wxString("Overwrite already selected facets"), m_overwrite_selected);
|
||||||
|
if (m_imgui->button("Enforce"))
|
||||||
|
select_facets_by_angle(m_angle_threshold_deg, m_overwrite_selected, false);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (m_imgui->button("Block"))
|
||||||
|
select_facets_by_angle(m_angle_threshold_deg, m_overwrite_selected, true);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (m_imgui->button("Cancel"))
|
||||||
|
m_setting_angle = false;
|
||||||
|
m_imgui->end();
|
||||||
|
if (! m_setting_angle)
|
||||||
|
m_parent.set_as_dirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoFdmSupports::on_is_activable() const
|
bool GLGizmoFdmSupports::on_is_activable() const
|
||||||
|
@ -680,6 +748,7 @@ void GLGizmoFdmSupports::on_set_state()
|
||||||
}
|
}
|
||||||
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
|
||||||
// we are actually shutting down
|
// we are actually shutting down
|
||||||
|
m_setting_angle = false;
|
||||||
wxGetApp().plater()->leave_gizmos_stack();
|
wxGetApp().plater()->leave_gizmos_stack();
|
||||||
{
|
{
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned off")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("FDM gizmo turned off")));
|
||||||
|
|
|
@ -61,10 +61,15 @@ private:
|
||||||
void update_model_object() const;
|
void update_model_object() const;
|
||||||
void update_from_model_object();
|
void update_from_model_object();
|
||||||
|
|
||||||
|
void select_facets_by_angle(float threshold, bool overwrite, bool block);
|
||||||
|
bool m_overwrite_selected = false;
|
||||||
|
float m_angle_threshold_deg = 45.f;
|
||||||
|
|
||||||
bool is_mesh_point_clipped(const Vec3d& point) const;
|
bool is_mesh_point_clipped(const Vec3d& point) const;
|
||||||
|
|
||||||
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;
|
||||||
|
bool m_setting_angle = false;
|
||||||
|
|
||||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||||
|
|
Loading…
Add table
Reference in a new issue