SLA gizmo keeps track of current status of the points, enables the user to erase all points

This commit is contained in:
Lukas Matena 2019-02-27 16:23:10 +01:00
parent a76bd40c62
commit 4eb4e40746
6 changed files with 68 additions and 28 deletions

View File

@ -592,6 +592,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs)
this->input_file = rhs.input_file; this->input_file = rhs.input_file;
this->config = rhs.config; this->config = rhs.config;
this->sla_support_points = rhs.sla_support_points; this->sla_support_points = rhs.sla_support_points;
this->sla_points_status = rhs.sla_points_status;
this->layer_height_ranges = rhs.layer_height_ranges; this->layer_height_ranges = rhs.layer_height_ranges;
this->layer_height_profile = rhs.layer_height_profile; this->layer_height_profile = rhs.layer_height_profile;
this->origin_translation = rhs.origin_translation; this->origin_translation = rhs.origin_translation;
@ -625,6 +626,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs)
this->input_file = std::move(rhs.input_file); this->input_file = std::move(rhs.input_file);
this->config = std::move(rhs.config); this->config = std::move(rhs.config);
this->sla_support_points = std::move(rhs.sla_support_points); this->sla_support_points = std::move(rhs.sla_support_points);
this->sla_points_status = std::move(rhs.sla_points_status);
this->layer_height_ranges = std::move(rhs.layer_height_ranges); this->layer_height_ranges = std::move(rhs.layer_height_ranges);
this->layer_height_profile = std::move(rhs.layer_height_profile); this->layer_height_profile = std::move(rhs.layer_height_profile);
this->origin_translation = std::move(rhs.origin_translation); this->origin_translation = std::move(rhs.origin_translation);
@ -1130,6 +1132,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
if (keep_upper) { if (keep_upper) {
upper->set_model(nullptr); upper->set_model(nullptr);
upper->sla_support_points.clear(); upper->sla_support_points.clear();
upper->sla_points_status = sla::PointsStatus::None;
upper->clear_volumes(); upper->clear_volumes();
upper->input_file = ""; upper->input_file = "";
} }
@ -1137,6 +1140,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
if (keep_lower) { if (keep_lower) {
lower->set_model(nullptr); lower->set_model(nullptr);
lower->sla_support_points.clear(); lower->sla_support_points.clear();
lower->sla_points_status = sla::PointsStatus::None;
lower->clear_volumes(); lower->clear_volumes();
lower->input_file = ""; lower->input_file = "";
} }

View File

@ -180,6 +180,9 @@ public:
// saved in mesh coordinates to allow using them for several instances. // saved in mesh coordinates to allow using them for several instances.
// The format is (x, y, z, point_size, supports_island) // The format is (x, y, z, point_size, supports_island)
std::vector<sla::SupportPoint> sla_support_points; std::vector<sla::SupportPoint> sla_support_points;
// To keep track of where the points came from (used for synchronization between
// the SLA gizmo and the backend).
sla::PointsStatus sla_points_status = sla::PointsStatus::None;
/* This vector accumulates the total translation applied to the object by the /* This vector accumulates the total translation applied to the object by the
center_around_origin() method. Callers might want to apply the same translation center_around_origin() method. Callers might want to apply the same translation

View File

@ -15,6 +15,14 @@ class TriangleMesh;
namespace sla { namespace sla {
// An enum to keep track of where the current points on the ModelObject came from.
enum class PointsStatus {
None, // No points were generated so far.
Generating, // The autogeneration algorithm triggered, but not yet finished.
AutoGenerated, // Points were autogenerated (i.e. copied from the backend).
UserModified // User has done some edits.
};
struct SupportPoint { struct SupportPoint {
Vec3f pos; Vec3f pos;
float head_front_radius; float head_front_radius;

View File

@ -342,6 +342,17 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
if (it_print_object_status != print_object_status.end()) if (it_print_object_status != print_object_status.end())
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints)); update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
} }
if (model_object.sla_points_status != model_object_new.sla_points_status) {
// Change of this status should invalidate support points. The points themselves are not enough, there are none
// in case that nothing was generated OR that points were autogenerated already and not copied to the front-end.
// These cases can only be differentiated by checking the status change. However, changing from 'Generating' should NOT
// invalidate - that would keep stopping the background processing without a reason.
if (model_object.sla_points_status != sla::PointsStatus::Generating)
if (it_print_object_status != print_object_status.end())
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
model_object.sla_points_status = model_object_new.sla_points_status;
}
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step. // Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
model_object.name = model_object_new.name; model_object.name = model_object_new.name;
model_object.input_file = model_object_new.input_file; model_object.input_file = model_object_new.input_file;
@ -630,10 +641,11 @@ void SLAPrint::process()
BOOST_LOG_TRIVIAL(debug) << "Support point count " BOOST_LOG_TRIVIAL(debug) << "Support point count "
<< mo.sla_support_points.size(); << mo.sla_support_points.size();
// If there are no points on the front-end, we will do the // Unless the user modified the points or we already did the calculation, we will do
// autoplacement. Otherwise we will just blindly copy the frontend data // the autoplacement. Otherwise we will just blindly copy the frontend data
// into the backend cache. // into the backend cache.
if(mo.sla_support_points.empty()) { if (mo.sla_points_status != sla::PointsStatus::UserModified) {
// calculate heights of slices (slices are calculated already) // calculate heights of slices (slices are calculated already)
double lh = po.m_config.layer_height.getFloat(); double lh = po.m_config.layer_height.getFloat();
@ -645,7 +657,9 @@ void SLAPrint::process()
this->throw_if_canceled(); this->throw_if_canceled();
SLAAutoSupports::Config config; SLAAutoSupports::Config config;
const SLAPrintObjectConfig& cfg = po.config(); const SLAPrintObjectConfig& cfg = po.config();
config.density_relative = float(cfg.support_points_density_relative / 100.f); // the config value is in percents
// the density config value is in percents:
config.density_relative = float(cfg.support_points_density_relative / 100.f);
config.minimal_distance = float(cfg.support_points_minimal_distance); config.minimal_distance = float(cfg.support_points_minimal_distance);
// Construction of this object does the calculation. // Construction of this object does the calculation.
@ -669,7 +683,7 @@ void SLAPrint::process()
report_status(*this, -1, L("Generating support points"), SlicingStatus::RELOAD_SLA_SUPPORT_POINTS); report_status(*this, -1, L("Generating support points"), SlicingStatus::RELOAD_SLA_SUPPORT_POINTS);
} }
else { else {
// There are some points on the front-end, no calculation will be done. // There are either some points on the front-end, or the user removed them on purpose. No calculation will be done.
po.m_supportdata->support_points = po.transformed_support_points(); po.m_supportdata->support_points = po.transformed_support_points();
} }
}; };

View File

@ -1789,12 +1789,12 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const G
if (is_mesh_update_necessary()) if (is_mesh_update_necessary())
update_mesh(); update_mesh();
// If there are no points, let's ask the backend if it calculated some.
if (m_editing_mode_cache.empty())
get_data_from_backend();
if (m_model_object != m_old_model_object) if (m_model_object != m_old_model_object)
m_editing_mode = false; m_editing_mode = false;
if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified)
get_data_from_backend();
if (m_state == On) { if (m_state == On) {
m_parent.toggle_model_objects_visibility(false); m_parent.toggle_model_objects_visibility(false);
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance); m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
@ -2296,8 +2296,7 @@ RENDER_AGAIN:
m_imgui->text(" "); // vertical gap m_imgui->text(" "); // vertical gap
bool apply_changes = m_imgui->button(_(L("Apply changes"))); if (m_imgui->button(_(L("Apply changes")))) {
if (apply_changes) {
editing_mode_apply_changes(); editing_mode_apply_changes();
force_refresh = true; force_refresh = true;
} }
@ -2308,24 +2307,28 @@ RENDER_AGAIN:
force_refresh = true; force_refresh = true;
} }
} }
else { else { // not in editing mode:
/* ImGui::PushItemWidth(50.0f); /*ImGui::PushItemWidth(100.0f);
m_imgui->text(_(L("Minimal points distance: "))); m_imgui->text(_(L("Minimal points distance: ")));
ImGui::SameLine(); ImGui::SameLine();
bool value_changed = ImGui::InputDouble("mm", &m_minimal_point_distance, 0.0f, 0.0f, "%.2f"); bool value_changed = ImGui::SliderFloat("", &m_minimal_point_distance, 0.f, 20.f, "%.f mm");
m_imgui->text(_(L("Support points density: "))); m_imgui->text(_(L("Support points density: ")));
ImGui::SameLine(); ImGui::SameLine();
value_changed |= ImGui::InputDouble("%", &m_density, 0.0f, 0.0f, "%.f");*/ value_changed |= ImGui::SliderFloat(" ", &m_density, 0.f, 200.f, "%.f %%");*/
bool generate = m_imgui->button(_(L("Auto-generate points [A]"))); bool generate = m_imgui->button(_(L("Auto-generate points [A]")));
if (generate) if (generate)
auto_generate(); auto_generate();
m_imgui->text("");
m_imgui->text(""); m_imgui->text("");
if (m_imgui->button(_(L("Manual editing [M]")))) if (m_imgui->button(_(L("Manual editing [M]"))))
switch_to_editing_mode(); switch_to_editing_mode();
m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" :
(m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" :
(m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" :
(m_model_object->sla_points_status == sla::PointsStatus::Generating ? "Generation in progress..." : "UNKNOWN STATUS"))));
} }
m_imgui->end(); m_imgui->end();
@ -2448,16 +2451,18 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
// If there are no changes, don't touch the front-end. The data in the cache could have been // If there are no changes, don't touch the front-end. The data in the cache could have been
// taken from the backend and copying them to ModelObject would needlessly invalidate them. // taken from the backend and copying them to ModelObject would needlessly invalidate them.
if (m_unsaved_changes) { if (m_unsaved_changes) {
m_model_object->sla_points_status = sla::PointsStatus::UserModified;
m_model_object->sla_support_points.clear(); m_model_object->sla_support_points.clear();
for (const std::pair<sla::SupportPoint, bool>& point_and_selection : m_editing_mode_cache) for (const std::pair<sla::SupportPoint, bool>& point_and_selection : m_editing_mode_cache)
m_model_object->sla_support_points.push_back(point_and_selection.first); m_model_object->sla_support_points.push_back(point_and_selection.first);
// Recalculate support structures once the editing mode is left.
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
} }
m_editing_mode = false; m_editing_mode = false;
m_unsaved_changes = false; m_unsaved_changes = false;
// Recalculate support structures once the editing mode is left.
// m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
} }
@ -2476,10 +2481,15 @@ void GLGizmoSlaSupports::get_data_from_backend()
{ {
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) { if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) {
m_editing_mode_cache.clear();
const std::vector<sla::SupportPoint>& points = po->get_support_points(); const std::vector<sla::SupportPoint>& points = po->get_support_points();
auto mat = po->trafo().inverse().cast<float>(); auto mat = po->trafo().inverse().cast<float>();
for (unsigned int i=0; i<points.size();++i) for (unsigned int i=0; i<points.size();++i)
m_editing_mode_cache.emplace_back(sla::SupportPoint(mat * points[i].pos, points[i].head_front_radius, points[i].is_new_island), false); m_editing_mode_cache.emplace_back(sla::SupportPoint(mat * points[i].pos, points[i].head_front_radius, points[i].is_new_island), false);
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified)
m_model_object->sla_points_status = sla::PointsStatus::AutoGenerated;
break; break;
} }
} }
@ -2497,8 +2507,9 @@ void GLGizmoSlaSupports::auto_generate()
"Are you sure you want to do it?\n" "Are you sure you want to do it?\n"
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO); )), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
if (m_model_object->sla_support_points.empty() || dlg.ShowModal() == wxID_YES) { if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || dlg.ShowModal() == wxID_YES) {
m_model_object->sla_support_points.clear(); m_model_object->sla_support_points.clear();
m_model_object->sla_points_status = sla::PointsStatus::Generating;
m_editing_mode_cache.clear(); m_editing_mode_cache.clear();
wxGetApp().plater()->reslice_SLA_supports(*m_model_object); wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
} }

View File

@ -489,19 +489,19 @@ private:
#endif // not ENABLE_IMGUI #endif // not ENABLE_IMGUI
bool m_lock_unique_islands = false; bool m_lock_unique_islands = false;
bool m_editing_mode = false; bool m_editing_mode = false; // Is editing mode active?
bool m_old_editing_state = false; bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes).
float m_new_point_head_diameter = 0.4f; float m_new_point_head_diameter = 0.4f; // Size of a new point.
double m_minimal_point_distance = 20.; float m_minimal_point_distance = 20.f;
double m_density = 100.; float m_density = 100.f;
std::vector<std::pair<sla::SupportPoint, bool>> m_editing_mode_cache; // a support point and whether it is currently selected std::vector<std::pair<sla::SupportPoint, bool>> m_editing_mode_cache; // a support point and whether it is currently selected
bool m_selection_rectangle_active = false; bool m_selection_rectangle_active = false;
Vec2d m_selection_rectangle_start_corner; Vec2d m_selection_rectangle_start_corner;
Vec2d m_selection_rectangle_end_corner; Vec2d m_selection_rectangle_end_corner;
bool m_ignore_up_event = false; bool m_ignore_up_event = false;
bool m_combo_box_open = false; bool m_combo_box_open = false; // To ensure proper rendering of the imgui combobox.
bool m_unsaved_changes = false; bool m_unsaved_changes = false; // Are there unsaved changes in manual mode?
bool m_selection_empty = true; bool m_selection_empty = true;
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state) EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
int m_canvas_width; int m_canvas_width;