SPE-1606 - Fixed a bunch of bugs/crashes related to visualizing original or processed volumes in 3D scene after slicing using SLA printers when multiple objects are on the printbed
This commit is contained in:
parent
15daac0811
commit
d9dde32b78
@ -36,6 +36,8 @@
|
|||||||
#define ENABLE_MATRICES_DEBUG 0
|
#define ENABLE_MATRICES_DEBUG 0
|
||||||
// Shows an imgui dialog containing data from class ObjectManipulation
|
// Shows an imgui dialog containing data from class ObjectManipulation
|
||||||
#define ENABLE_OBJECT_MANIPULATION_DEBUG 0
|
#define ENABLE_OBJECT_MANIPULATION_DEBUG 0
|
||||||
|
// Shows an imgui dialog containing data for class GLCanvas3D::SLAView
|
||||||
|
#define ENABLE_SLA_VIEW_DEBUG_WINDOW 1
|
||||||
|
|
||||||
|
|
||||||
// Enable rendering of objects using environment map
|
// Enable rendering of objects using environment map
|
||||||
|
@ -1070,132 +1070,246 @@ void GLCanvas3D::load_arrange_settings()
|
|||||||
m_arrange_settings_fff_seq_print.alignment = arr_alignment ;
|
m_arrange_settings_fff_seq_print.alignment = arr_alignment ;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int processed_object_idx(const Model& model, const SLAPrint& sla_print, const GLVolumePtrs& volumes)
|
static std::vector<int> processed_objects_idxs(const Model& model, const SLAPrint& sla_print, const GLVolumePtrs& volumes)
|
||||||
{
|
{
|
||||||
for (const GLVolume* v : volumes) {
|
std::vector<int> ret;
|
||||||
if (v->volume_idx() == -(int)slaposDrillHoles) {
|
GLVolumePtrs matching_volumes;
|
||||||
const int mo_idx = v->object_idx();
|
std::copy_if(volumes.begin(), volumes.end(), std::back_inserter(matching_volumes), [](GLVolume* v) {
|
||||||
const ModelObject* model_object = (mo_idx < (int)model.objects.size()) ? model.objects[mo_idx] : nullptr;
|
return v->volume_idx() == -(int)slaposDrillHoles; });
|
||||||
if (model_object != nullptr && model_object->instances[v->instance_idx()]->is_printable()) {
|
for (const GLVolume* v : matching_volumes) {
|
||||||
const SLAPrintObject* print_object = sla_print.get_print_object_by_model_object_id(model_object->id());
|
const int mo_idx = v->object_idx();
|
||||||
if (print_object != nullptr && print_object->get_parts_to_slice().size() > 1)
|
const ModelObject* model_object = (mo_idx < (int)model.objects.size()) ? model.objects[mo_idx] : nullptr;
|
||||||
return mo_idx;
|
if (model_object != nullptr && model_object->instances[v->instance_idx()]->is_printable()) {
|
||||||
}
|
const SLAPrintObject* print_object = sla_print.get_print_object_by_model_object_id(model_object->id());
|
||||||
|
if (print_object != nullptr && print_object->get_parts_to_slice().size() > 1)
|
||||||
|
ret.push_back(mo_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::sort(ret.begin(), ret.end());
|
||||||
return -1;
|
ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
|
||||||
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
GLCanvas3D::ESLAViewType GLCanvas3D::SLAView::detect_type(const GLVolumePtrs& volumes)
|
static bool composite_id_match(const GLVolume::CompositeID& id1, const GLVolume::CompositeID& id2)
|
||||||
{
|
{
|
||||||
m_type = ESLAViewType::Original;
|
return id1.object_id == id2.object_id && id1.instance_id == id2.instance_id;
|
||||||
if (m_allow_type_detection) {
|
}
|
||||||
for (const GLVolume* v : volumes) {
|
|
||||||
if (v->volume_idx() == -(int)slaposDrillHoles) {
|
void GLCanvas3D::SLAView::detect_type_from_volumes(const GLVolumePtrs& volumes)
|
||||||
m_type = ESLAViewType::Processed;
|
{
|
||||||
break;
|
for (auto& [id, type] : m_instances_cache) {
|
||||||
}
|
type = ESLAViewType::Original;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const GLVolume* v : volumes) {
|
||||||
|
if (v->volume_idx() == -(int)slaposDrillHoles) {
|
||||||
|
const InstancesCacheItem* instance = find_instance_item(v->composite_id);
|
||||||
|
assert(instance != nullptr);
|
||||||
|
set_type(instance->first, ESLAViewType::Processed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_parent.set_sla_view_type(m_type);
|
|
||||||
m_allow_type_detection = false;
|
|
||||||
return m_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::SLAView::set_type(ESLAViewType type) {
|
void GLCanvas3D::SLAView::set_type(ESLAViewType new_type)
|
||||||
if (m_type != type) {
|
{
|
||||||
m_type = type;
|
for (auto& [id, type] : m_instances_cache) {
|
||||||
return true;
|
type = new_type;
|
||||||
|
if (new_type == ESLAViewType::Processed)
|
||||||
|
select_full_instance(id);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::SLAView::update_volumes(GLVolumePtrs& volumes)
|
void GLCanvas3D::SLAView::set_type(const GLVolume::CompositeID& id, ESLAViewType new_type)
|
||||||
|
{
|
||||||
|
InstancesCacheItem* instance = find_instance_item(id);
|
||||||
|
assert(instance != nullptr);
|
||||||
|
instance->second = new_type;
|
||||||
|
if (new_type == ESLAViewType::Processed)
|
||||||
|
select_full_instance(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::SLAView::update_volumes_visibility(GLVolumePtrs& volumes)
|
||||||
{
|
{
|
||||||
const SLAPrint* sla_print = m_parent.sla_print();
|
const SLAPrint* sla_print = m_parent.sla_print();
|
||||||
const int mo_idx = (sla_print != nullptr) ? processed_object_idx(*m_parent.get_model(), *sla_print, volumes) : -1;
|
const std::vector<int> mo_idxs = (sla_print != nullptr) ? processed_objects_idxs(*m_parent.get_model(), *sla_print, volumes) : std::vector<int>();
|
||||||
const bool show_processed = m_type == ESLAViewType::Processed && mo_idx != -1;
|
|
||||||
|
|
||||||
auto show = [show_processed](const GLVolume& v) {
|
|
||||||
return show_processed ? v.volume_idx() < 0 : v.volume_idx() != -(int)slaposDrillHoles;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
||||||
|
|
||||||
for (GLVolume* v : volumes) {
|
for (GLVolume* v : volumes) {
|
||||||
v->is_active = v->object_idx() != mo_idx || show(*v);
|
const int obj_idx = v->object_idx();
|
||||||
|
bool active = std::find(mo_idxs.begin(), mo_idxs.end(), obj_idx) == mo_idxs.end();
|
||||||
|
if (!active) {
|
||||||
|
const InstancesCacheItem* instance = find_instance_item(v->composite_id);
|
||||||
|
assert(instance != nullptr);
|
||||||
|
active = (instance->second == ESLAViewType::Processed) ? v->volume_idx() < 0 : v->volume_idx() != -(int)slaposDrillHoles;
|
||||||
|
}
|
||||||
|
v->is_active = active;
|
||||||
auto it = std::find_if(raycasters->begin(), raycasters->end(), [v](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == v->mesh_raycaster.get(); });
|
auto it = std::find_if(raycasters->begin(), raycasters->end(), [v](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == v->mesh_raycaster.get(); });
|
||||||
if (it != raycasters->end())
|
if (it != raycasters->end())
|
||||||
(*it)->set_active(v->is_active);
|
(*it)->set_active(v->is_active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::SLAView::update_instances_cache(const std::vector<std::pair<GLVolume::CompositeID, GLVolume::CompositeID>>& new_to_old_ids_map)
|
||||||
|
{
|
||||||
|
// First, extract current instances list from the volumes
|
||||||
|
const GLVolumePtrs& volumes = m_parent.get_volumes().volumes;
|
||||||
|
std::vector<InstancesCacheItem> new_instances_cache;
|
||||||
|
for (const GLVolume* v : volumes) {
|
||||||
|
new_instances_cache.emplace_back(v->composite_id, ESLAViewType::Original);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(new_instances_cache.begin(), new_instances_cache.end(),
|
||||||
|
[](const InstancesCacheItem& i1, const InstancesCacheItem& i2) {
|
||||||
|
return i1.first.object_id < i2.first.object_id || (i1.first.object_id == i2.first.object_id && i1.first.instance_id < i2.first.instance_id); });
|
||||||
|
|
||||||
|
new_instances_cache.erase(std::unique(new_instances_cache.begin(), new_instances_cache.end(),
|
||||||
|
[](const InstancesCacheItem& i1, const InstancesCacheItem& i2) {
|
||||||
|
return composite_id_match(i1.first, i2.first); }), new_instances_cache.end());
|
||||||
|
|
||||||
|
// Second, update instances type from previous state
|
||||||
|
for (auto& inst_type : new_instances_cache) {
|
||||||
|
const auto map_to_old_it = std::find_if(new_to_old_ids_map.begin(), new_to_old_ids_map.end(), [&inst_type](const std::pair<GLVolume::CompositeID, GLVolume::CompositeID>& item) {
|
||||||
|
return composite_id_match(inst_type.first, item.first); });
|
||||||
|
|
||||||
|
const GLVolume::CompositeID old_inst_id = (map_to_old_it != new_to_old_ids_map.end()) ? map_to_old_it->second : inst_type.first;
|
||||||
|
const InstancesCacheItem* old_instance = find_instance_item(old_inst_id);
|
||||||
|
if (old_instance != nullptr)
|
||||||
|
inst_type.second = old_instance->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_instances_cache = new_instances_cache;
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::SLAView::render_switch_button()
|
void GLCanvas3D::SLAView::render_switch_button()
|
||||||
{
|
{
|
||||||
const SLAPrint* sla_print = m_parent.sla_print();
|
const SLAPrint* sla_print = m_parent.sla_print();
|
||||||
const int mo_idx = (sla_print != nullptr) ? processed_object_idx(*m_parent.get_model(), *sla_print, m_parent.get_volumes().volumes) : -1;
|
if (sla_print == nullptr)
|
||||||
if (mo_idx == -1)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const BoundingBoxf ss_box = m_parent.get_selection().get_screen_space_bounding_box();
|
const std::vector<int> mo_idxs = processed_objects_idxs(*m_parent.get_model(), *sla_print, m_parent.get_volumes().volumes);
|
||||||
if (ss_box.defined) {
|
if (mo_idxs.empty())
|
||||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
return;
|
||||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
Selection& selection = m_parent.get_selection();
|
||||||
ImGui::SetNextWindowPos(ImVec2((float)ss_box.max.x(), (float)ss_box.center().y()), ImGuiCond_Always, ImVec2(0.0, 0.5));
|
const int obj_idx = selection.get_object_idx();
|
||||||
imgui.begin(std::string("SLAViewSwitch"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration);
|
if (std::find(mo_idxs.begin(), mo_idxs.end(), obj_idx) == mo_idxs.end())
|
||||||
const float icon_size = 1.5 * ImGui::GetTextLineHeight();
|
return;
|
||||||
if (imgui.draw_radio_button(_u8L("SLA view"), 1.5f * icon_size, true, [this, &imgui](ImGuiWindow& window, const ImVec2& pos, float size) {
|
|
||||||
|
const int inst_idx = selection.get_instance_idx();
|
||||||
|
if (inst_idx < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const GLVolume::CompositeID composite_id(obj_idx, 0, inst_idx);
|
||||||
|
const InstancesCacheItem* sel_instance = find_instance_item(composite_id);
|
||||||
|
if (sel_instance == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const ESLAViewType type = sel_instance->second;
|
||||||
|
|
||||||
|
BoundingBoxf ss_box;
|
||||||
|
if (m_use_instance_bbox) {
|
||||||
|
const Selection::EMode mode = selection.get_mode();
|
||||||
|
if (obj_idx >= 0 && inst_idx >= 0) {
|
||||||
|
const Selection::IndicesList selected_idxs = selection.get_volume_idxs();
|
||||||
|
std::vector<unsigned int> idxs_as_vector;
|
||||||
|
idxs_as_vector.assign(selected_idxs.begin(), selected_idxs.end());
|
||||||
|
selection.add_instance(obj_idx, inst_idx, true);
|
||||||
|
ss_box = selection.get_screen_space_bounding_box();
|
||||||
|
selection.add_volumes(mode, idxs_as_vector, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ss_box.defined)
|
||||||
|
ss_box = selection.get_screen_space_bounding_box();
|
||||||
|
assert(ss_box.defined);
|
||||||
|
|
||||||
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
|
ImGui::SetNextWindowPos(ImVec2((float)ss_box.max.x(), (float)ss_box.center().y()), ImGuiCond_Always, ImVec2(0.0, 0.5));
|
||||||
|
imgui.begin(std::string("SLAViewSwitch"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration);
|
||||||
|
const float icon_size = 1.5 * ImGui::GetTextLineHeight();
|
||||||
|
if (imgui.draw_radio_button(_u8L("SLA view"), 1.5f * icon_size, true,
|
||||||
|
[this, &imgui, sel_instance](ImGuiWindow& window, const ImVec2& pos, float size) {
|
||||||
wchar_t icon_id;
|
wchar_t icon_id;
|
||||||
switch (m_type)
|
switch (sel_instance->second)
|
||||||
{
|
{
|
||||||
case ESLAViewType::Original: { icon_id = ImGui::SlaViewProcessed; break; }
|
case ESLAViewType::Original: { icon_id = ImGui::SlaViewProcessed; break; }
|
||||||
case ESLAViewType::Processed: { icon_id = ImGui::SlaViewOriginal; break; }
|
case ESLAViewType::Processed: { icon_id = ImGui::SlaViewOriginal; break; }
|
||||||
default: { assert(false); break; }
|
default: { assert(false); break; }
|
||||||
}
|
}
|
||||||
imgui.draw_icon(window, pos, size, icon_id);
|
imgui.draw_icon(window, pos, size, icon_id);
|
||||||
|
})) {
|
||||||
})) {
|
switch (sel_instance->second)
|
||||||
switch (m_type)
|
{
|
||||||
{
|
case ESLAViewType::Original: { m_parent.set_sla_view_type(sel_instance->first, ESLAViewType::Processed); break; }
|
||||||
case ESLAViewType::Original: { m_parent.set_sla_view_type(ESLAViewType::Processed); break; }
|
case ESLAViewType::Processed: { m_parent.set_sla_view_type(sel_instance->first, ESLAViewType::Original); break; }
|
||||||
case ESLAViewType::Processed: { m_parent.set_sla_view_type(ESLAViewType::Original); break; }
|
default: { assert(false); break; }
|
||||||
default: { assert(false); break; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
|
|
||||||
ImGui::BeginTooltip();
|
|
||||||
wxString tooltip;
|
|
||||||
switch (m_type)
|
|
||||||
{
|
|
||||||
case ESLAViewType::Original: { tooltip = _L("Show as processed"); break; }
|
|
||||||
case ESLAViewType::Processed: { tooltip = _L("Show as original"); break; }
|
|
||||||
default: { assert(false); break; }
|
|
||||||
}
|
|
||||||
|
|
||||||
imgui.text(tooltip);
|
|
||||||
ImGui::EndTooltip();
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
imgui.end();
|
|
||||||
ImGui::PopStyleColor(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
wxString tooltip;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ESLAViewType::Original: { tooltip = _L("Show as processed"); break; }
|
||||||
|
case ESLAViewType::Processed: { tooltip = _L("Show as original"); break; }
|
||||||
|
default: { assert(false); break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
imgui.text(tooltip);
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
imgui.end();
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void GLCanvas3D::SLAView::render_debug_window()
|
#if ENABLE_SLA_VIEW_DEBUG_WINDOW
|
||||||
//{
|
void GLCanvas3D::SLAView::render_debug_window()
|
||||||
// ImGuiWrapper& imgui = *wxGetApp().imgui();
|
{
|
||||||
// imgui.begin(std::string("SLAView"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize);
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
// imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, "Type:");
|
imgui.begin(std::string("SLAView"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize);
|
||||||
// ImGui::SameLine();
|
for (const auto& [id, type] : m_instances_cache) {
|
||||||
// const std::string text = (m_type == ESLAViewType::Original) ? "Original" : "Processed";
|
imgui.text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, "(" + std::to_string(id.object_id) + ", " + std::to_string(id.instance_id) + ")");
|
||||||
// imgui.text_colored(ImGui::GetStyleColorVec4(ImGuiCol_Text), text);
|
ImGui::SameLine();
|
||||||
// imgui.end();
|
imgui.text_colored(ImGui::GetStyleColorVec4(ImGuiCol_Text), (type == ESLAViewType::Original) ? "Original" : "Processed");
|
||||||
//}
|
}
|
||||||
|
if (!m_instances_cache.empty())
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
imgui.checkbox("Use instance bounding box", m_use_instance_bbox);
|
||||||
|
imgui.end();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SLA_VIEW_DEBUG_WINDOW
|
||||||
|
|
||||||
|
GLCanvas3D::SLAView::InstancesCacheItem* GLCanvas3D::SLAView::find_instance_item(const GLVolume::CompositeID& id)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(m_instances_cache.begin(), m_instances_cache.end(),
|
||||||
|
[&id](const InstancesCacheItem& item) { return composite_id_match(item.first, id); });
|
||||||
|
return (it == m_instances_cache.end()) ? nullptr : &(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::SLAView::select_full_instance(const GLVolume::CompositeID& id)
|
||||||
|
{
|
||||||
|
bool extended_selection = false;
|
||||||
|
Selection& selection = m_parent.get_selection();
|
||||||
|
const Selection::ObjectIdxsToInstanceIdxsMap& sel_cache = selection.get_content();
|
||||||
|
auto obj_it = sel_cache.find(id.object_id);
|
||||||
|
if (obj_it != sel_cache.end()) {
|
||||||
|
auto inst_it = std::find(obj_it->second.begin(), obj_it->second.end(), id.instance_id);
|
||||||
|
if (inst_it != obj_it->second.end()) {
|
||||||
|
selection.add_instance(id.object_id, id.instance_id);
|
||||||
|
extended_selection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extended_selection)
|
||||||
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
|
||||||
|
}
|
||||||
|
|
||||||
PrinterTechnology GLCanvas3D::current_printer_technology() const
|
PrinterTechnology GLCanvas3D::current_printer_technology() const
|
||||||
{
|
{
|
||||||
@ -1775,7 +1889,9 @@ void GLCanvas3D::render()
|
|||||||
const GLGizmosManager::EType type = m_gizmos.get_current_type();
|
const GLGizmosManager::EType type = m_gizmos.get_current_type();
|
||||||
if (type == GLGizmosManager::EType::Undefined)
|
if (type == GLGizmosManager::EType::Undefined)
|
||||||
m_sla_view.render_switch_button();
|
m_sla_view.render_switch_button();
|
||||||
// m_sla_view.render_debug_window();
|
#if ENABLE_SLA_VIEW_DEBUG_WINDOW
|
||||||
|
m_sla_view.render_debug_window();
|
||||||
|
#endif // ENABLE_SLA_VIEW_DEBUG_WINDOW
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tooltip;
|
std::string tooltip;
|
||||||
@ -2017,6 +2133,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||||||
size_t volume_idx;
|
size_t volume_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::vector<std::pair<GLVolume::CompositeID, GLVolume::CompositeID>> new_to_old_ids_map;
|
||||||
|
|
||||||
// SLA steps to pull the preview meshes for.
|
// SLA steps to pull the preview meshes for.
|
||||||
typedef std::array<SLAPrintObjectStep, 3> SLASteps;
|
typedef std::array<SLAPrintObjectStep, 3> SLASteps;
|
||||||
SLASteps sla_steps = { slaposDrillHoles, slaposSupportTree, slaposPad };
|
SLASteps sla_steps = { slaposDrillHoles, slaposSupportTree, slaposPad };
|
||||||
@ -2164,12 +2282,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||||||
for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++ obj_idx) {
|
for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++ obj_idx) {
|
||||||
const ModelObject &model_object = *m_model->objects[obj_idx];
|
const ModelObject &model_object = *m_model->objects[obj_idx];
|
||||||
for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++ volume_idx) {
|
for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++ volume_idx) {
|
||||||
const ModelVolume &model_volume = *model_object.volumes[volume_idx];
|
const ModelVolume &model_volume = *model_object.volumes[volume_idx];
|
||||||
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
|
for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
|
||||||
const ModelInstance &model_instance = *model_object.instances[instance_idx];
|
const ModelInstance &model_instance = *model_object.instances[instance_idx];
|
||||||
ModelVolumeState key(model_volume.id(), model_instance.id());
|
ModelVolumeState key(model_volume.id(), model_instance.id());
|
||||||
auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
|
auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
|
||||||
assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
|
assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
|
||||||
if (it->new_geometry()) {
|
if (it->new_geometry()) {
|
||||||
// New volume.
|
// New volume.
|
||||||
auto it_old_volume = std::lower_bound(deleted_volumes.begin(), deleted_volumes.end(), GLVolumeState(it->composite_id), deleted_volumes_lower);
|
auto it_old_volume = std::lower_bound(deleted_volumes.begin(), deleted_volumes.end(), GLVolumeState(it->composite_id), deleted_volumes_lower);
|
||||||
@ -2182,15 +2300,17 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||||||
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx);
|
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx);
|
||||||
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
||||||
update_object_list = true;
|
update_object_list = true;
|
||||||
} else {
|
}
|
||||||
// Recycling an old GLVolume.
|
else {
|
||||||
GLVolume &existing_volume = *m_volumes.volumes[it->volume_idx];
|
// Recycling an old GLVolume.
|
||||||
|
GLVolume &existing_volume = *m_volumes.volumes[it->volume_idx];
|
||||||
assert(existing_volume.geometry_id == key.geometry_id);
|
assert(existing_volume.geometry_id == key.geometry_id);
|
||||||
// Update the Object/Volume/Instance indices into the current Model.
|
// Update the Object/Volume/Instance indices into the current Model.
|
||||||
if (existing_volume.composite_id != it->composite_id) {
|
if (existing_volume.composite_id != it->composite_id) {
|
||||||
existing_volume.composite_id = it->composite_id;
|
new_to_old_ids_map.push_back(std::make_pair(it->composite_id, existing_volume.composite_id));
|
||||||
update_object_list = true;
|
existing_volume.composite_id = it->composite_id;
|
||||||
}
|
update_object_list = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2241,7 +2361,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
|
// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
|
||||||
m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
|
const GLVolume::CompositeID new_id(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
|
||||||
|
new_to_old_ids_map.push_back(std::make_pair(new_id, m_volumes.volumes[it->volume_idx]->composite_id));
|
||||||
|
m_volumes.volumes[it->volume_idx]->composite_id = new_id;
|
||||||
m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
|
m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2252,9 +2374,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||||||
if (!instances[istep].empty())
|
if (!instances[istep].empty())
|
||||||
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
|
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_sla_view.detect_type(m_volumes.volumes) == ESLAViewType::Processed)
|
|
||||||
update_object_list = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
||||||
@ -2312,15 +2431,30 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||||||
else
|
else
|
||||||
m_selection.volumes_changed(map_glvolume_old_to_new);
|
m_selection.volumes_changed(map_glvolume_old_to_new);
|
||||||
|
|
||||||
if (printer_technology == ptSLA)
|
if (printer_technology == ptSLA) {
|
||||||
m_sla_view.update_volumes(m_volumes.volumes);
|
std::sort(new_to_old_ids_map.begin(), new_to_old_ids_map.end(),
|
||||||
|
[](const std::pair<GLVolume::CompositeID, GLVolume::CompositeID>& i1, const std::pair<GLVolume::CompositeID, GLVolume::CompositeID>& i2) {
|
||||||
|
return i1.first.object_id < i2.first.object_id || (i1.first.object_id == i2.first.object_id && i1.first.instance_id < i2.first.instance_id); });
|
||||||
|
|
||||||
|
new_to_old_ids_map.erase(std::unique(new_to_old_ids_map.begin(), new_to_old_ids_map.end(),
|
||||||
|
[](const std::pair<GLVolume::CompositeID, GLVolume::CompositeID>& i1, const std::pair<GLVolume::CompositeID, GLVolume::CompositeID>& i2) {
|
||||||
|
return composite_id_match(i1.first, i2.first); }), new_to_old_ids_map.end());
|
||||||
|
|
||||||
|
m_sla_view.update_instances_cache(new_to_old_ids_map);
|
||||||
|
if (m_sla_view_type_detection_active) {
|
||||||
|
m_sla_view.detect_type_from_volumes(m_volumes.volumes);
|
||||||
|
m_sla_view_type_detection_active = false;
|
||||||
|
}
|
||||||
|
m_sla_view.update_volumes_visibility(m_volumes.volumes);
|
||||||
|
update_object_list = true;
|
||||||
|
}
|
||||||
|
|
||||||
m_gizmos.update_data();
|
m_gizmos.update_data();
|
||||||
m_gizmos.refresh_on_off_state();
|
m_gizmos.refresh_on_off_state();
|
||||||
|
|
||||||
// Update the toolbar
|
// Update the toolbar
|
||||||
if (update_object_list)
|
if (update_object_list)
|
||||||
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
|
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
|
||||||
|
|
||||||
// checks for geometry outside the print volume to render it accordingly
|
// checks for geometry outside the print volume to render it accordingly
|
||||||
if (!m_volumes.empty()) {
|
if (!m_volumes.empty()) {
|
||||||
@ -4324,6 +4458,20 @@ std::pair<SlicingParameters, const std::vector<double>> GLCanvas3D::get_layers_h
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::set_sla_view_type(ESLAViewType type)
|
||||||
|
{
|
||||||
|
m_sla_view.set_type(type);
|
||||||
|
m_sla_view.update_volumes_visibility(m_volumes.volumes);
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::set_sla_view_type(const GLVolume::CompositeID& id, ESLAViewType type)
|
||||||
|
{
|
||||||
|
m_sla_view.set_type(id, type);
|
||||||
|
m_sla_view.update_volumes_visibility(m_volumes.volumes);
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::_is_shown_on_screen() const
|
bool GLCanvas3D::_is_shown_on_screen() const
|
||||||
{
|
{
|
||||||
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
|
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
|
||||||
|
@ -555,27 +555,33 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SLAView(GLCanvas3D& parent) : m_parent(parent) {}
|
explicit SLAView(GLCanvas3D& parent) : m_parent(parent) {}
|
||||||
void allow_type_detection(bool allow) { m_allow_type_detection = allow; }
|
void detect_type_from_volumes(const GLVolumePtrs& volumes);
|
||||||
ESLAViewType detect_type(const GLVolumePtrs& volumes);
|
void set_type(ESLAViewType type);
|
||||||
ESLAViewType get_type() const { return m_type; }
|
void set_type(const GLVolume::CompositeID& id, ESLAViewType type);
|
||||||
bool set_type(ESLAViewType type);
|
void update_volumes_visibility(GLVolumePtrs& volumes);
|
||||||
void update_volumes(GLVolumePtrs& volumes);
|
void update_instances_cache(const std::vector<std::pair<GLVolume::CompositeID, GLVolume::CompositeID>>& new_to_old_ids_map);
|
||||||
void render_switch_button();
|
void render_switch_button();
|
||||||
// void render_debug_window();
|
|
||||||
|
#if ENABLE_SLA_VIEW_DEBUG_WINDOW
|
||||||
|
void render_debug_window();
|
||||||
|
#endif // ENABLE_SLA_VIEW_DEBUG_WINDOW
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLCanvas3D& m_parent;
|
GLCanvas3D& m_parent;
|
||||||
ESLAViewType m_type{ ESLAViewType::Original };
|
typedef std::pair<GLVolume::CompositeID, ESLAViewType> InstancesCacheItem;
|
||||||
bool m_allow_type_detection{ false };
|
std::vector<InstancesCacheItem> m_instances_cache;
|
||||||
|
bool m_use_instance_bbox{ false };
|
||||||
|
|
||||||
|
InstancesCacheItem* find_instance_item(const GLVolume::CompositeID& id);
|
||||||
|
void select_full_instance(const GLVolume::CompositeID& id);
|
||||||
};
|
};
|
||||||
|
|
||||||
SLAView m_sla_view;
|
SLAView m_sla_view;
|
||||||
|
bool m_sla_view_type_detection_active{ false };
|
||||||
|
|
||||||
ArrangeSettings m_arrange_settings_fff, m_arrange_settings_sla,
|
ArrangeSettings m_arrange_settings_fff, m_arrange_settings_sla,
|
||||||
m_arrange_settings_fff_seq_print;
|
m_arrange_settings_fff_seq_print;
|
||||||
|
|
||||||
PrinterTechnology current_printer_technology() const;
|
|
||||||
|
|
||||||
bool is_arrange_alignment_enabled() const;
|
bool is_arrange_alignment_enabled() const;
|
||||||
|
|
||||||
template<class Self>
|
template<class Self>
|
||||||
@ -793,6 +799,8 @@ public:
|
|||||||
void zoom_to_gcode();
|
void zoom_to_gcode();
|
||||||
void select_view(const std::string& direction);
|
void select_view(const std::string& direction);
|
||||||
|
|
||||||
|
PrinterTechnology current_printer_technology() const;
|
||||||
|
|
||||||
void update_volumes_colors_by_extruder();
|
void update_volumes_colors_by_extruder();
|
||||||
|
|
||||||
bool is_dragging() const { return m_gizmos.is_dragging() || (m_moving && !m_mouse.scene_position.isApprox(m_mouse.drag.start_position_3D)); }
|
bool is_dragging() const { return m_gizmos.is_dragging() || (m_moving && !m_mouse.scene_position.isApprox(m_mouse.drag.start_position_3D)); }
|
||||||
@ -980,21 +988,9 @@ public:
|
|||||||
|
|
||||||
std::pair<SlicingParameters, const std::vector<double>> get_layers_height_data(int object_id);
|
std::pair<SlicingParameters, const std::vector<double>> get_layers_height_data(int object_id);
|
||||||
|
|
||||||
void set_sla_view_type(ESLAViewType type) {
|
void set_sla_view_type(ESLAViewType type);
|
||||||
if (type == ESLAViewType::Processed) {
|
void set_sla_view_type(const GLVolume::CompositeID& id, ESLAViewType type);
|
||||||
assert(!m_selection.is_empty());
|
void enable_sla_view_type_detection() { m_sla_view_type_detection_active = true; }
|
||||||
const GLVolume* v = m_selection.get_first_volume();
|
|
||||||
m_selection.add_instance(v->object_idx(), v->instance_idx());
|
|
||||||
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dirty = type != m_sla_view.get_type();
|
|
||||||
|
|
||||||
if (m_sla_view.set_type(type))
|
|
||||||
m_sla_view.update_volumes(m_volumes.volumes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void allow_sla_view_type_detection(bool allow) { m_sla_view.allow_type_detection(allow); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_shown_on_screen() const;
|
bool _is_shown_on_screen() const;
|
||||||
|
@ -749,7 +749,7 @@ void ObjectList::selection_changed()
|
|||||||
}
|
}
|
||||||
else if (type & itVolume) {
|
else if (type & itVolume) {
|
||||||
if (printer_technology() == ptSLA)
|
if (printer_technology() == ptSLA)
|
||||||
wxGetApp().plater()->canvas3D()->set_sla_view_type(GLCanvas3D::ESLAViewType::Original);
|
wxGetApp().plater()->canvas3D()->set_sla_view_type(scene_selection().get_first_volume()->composite_id, GLCanvas3D::ESLAViewType::Original);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,7 +978,8 @@ bool GLGizmosManager::activate_gizmo(EType type)
|
|||||||
return false; // gizmo refused to be turned on.
|
return false; // gizmo refused to be turned on.
|
||||||
}
|
}
|
||||||
|
|
||||||
m_parent.set_sla_view_type(GLCanvas3D::ESLAViewType::Original);
|
if (m_parent.current_printer_technology() == ptSLA)
|
||||||
|
m_parent.set_sla_view_type(GLCanvas3D::ESLAViewType::Original);
|
||||||
|
|
||||||
new_gizmo.register_raycasters_for_picking();
|
new_gizmo.register_raycasters_for_picking();
|
||||||
|
|
||||||
|
@ -3454,10 +3454,8 @@ unsigned int Plater::priv::update_restart_background_process(bool force_update_s
|
|||||||
{
|
{
|
||||||
// bitmask of UpdateBackgroundProcessReturnState
|
// bitmask of UpdateBackgroundProcessReturnState
|
||||||
unsigned int state = this->update_background_process(false);
|
unsigned int state = this->update_background_process(false);
|
||||||
if (force_update_scene || (state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0) {
|
if (force_update_scene || (state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0)
|
||||||
view3D->get_canvas3d()->allow_sla_view_type_detection(true);
|
|
||||||
view3D->reload_scene(false);
|
view3D->reload_scene(false);
|
||||||
}
|
|
||||||
|
|
||||||
if (force_update_preview)
|
if (force_update_preview)
|
||||||
this->preview->reload_print();
|
this->preview->reload_print();
|
||||||
@ -4082,8 +4080,10 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||||||
// If RELOAD_SLA_SUPPORT_POINTS, then the SLA gizmo is updated (reload_scene calls update_gizmos_data)
|
// If RELOAD_SLA_SUPPORT_POINTS, then the SLA gizmo is updated (reload_scene calls update_gizmos_data)
|
||||||
if (view3D->is_dragging())
|
if (view3D->is_dragging())
|
||||||
delayed_scene_refresh = true;
|
delayed_scene_refresh = true;
|
||||||
else
|
else {
|
||||||
|
view3D->get_canvas3d()->enable_sla_view_type_detection();
|
||||||
this->update_sla_scene();
|
this->update_sla_scene();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -6946,11 +6946,13 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
|
|||||||
|
|
||||||
p->config->set_key_value(opt_key, config.option(opt_key)->clone());
|
p->config->set_key_value(opt_key, config.option(opt_key)->clone());
|
||||||
if (opt_key == "printer_technology") {
|
if (opt_key == "printer_technology") {
|
||||||
this->set_printer_technology(config.opt_enum<PrinterTechnology>(opt_key));
|
const PrinterTechnology printer_technology = config.opt_enum<PrinterTechnology>(opt_key);
|
||||||
|
this->set_printer_technology(printer_technology);
|
||||||
p->sidebar->show_sliced_info_sizer(false);
|
p->sidebar->show_sliced_info_sizer(false);
|
||||||
p->reset_gcode_toolpaths();
|
p->reset_gcode_toolpaths();
|
||||||
p->view3D->get_canvas3d()->reset_sequential_print_clearance();
|
p->view3D->get_canvas3d()->reset_sequential_print_clearance();
|
||||||
p->view3D->get_canvas3d()->set_sla_view_type(GLCanvas3D::ESLAViewType::Original);
|
if (printer_technology == ptSLA)
|
||||||
|
p->view3D->get_canvas3d()->set_sla_view_type(GLCanvas3D::ESLAViewType::Original);
|
||||||
}
|
}
|
||||||
else if (opt_key == "bed_shape" || opt_key == "bed_custom_texture" || opt_key == "bed_custom_model") {
|
else if (opt_key == "bed_shape" || opt_key == "bed_custom_texture" || opt_key == "bed_custom_model") {
|
||||||
bed_shape_changed = true;
|
bed_shape_changed = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user