Re-enable volumes in SLA, use raycasters from canvas in supports gizmo

Got rid of HollowedMesh and Raycaster usage from GizmosCommon pool to prevent crashes
This commit is contained in:
tamasmeszaros 2022-10-20 14:14:25 +02:00
parent 15fa4c42d6
commit 9bc3410474
16 changed files with 269 additions and 207 deletions

View File

@ -28,7 +28,6 @@ class AABBMesh {
class AABBImpl; class AABBImpl;
const indexed_triangle_set* m_tm; const indexed_triangle_set* m_tm;
// double m_ground_level = 0/*, m_gnd_offset = 0*/;
std::unique_ptr<AABBImpl> m_aabb; std::unique_ptr<AABBImpl> m_aabb;
VertexFaceIndex m_vfidx; // vertex-face index VertexFaceIndex m_vfidx; // vertex-face index
@ -57,10 +56,6 @@ public:
~AABBMesh(); ~AABBMesh();
// inline double ground_level() const { return m_ground_level /*+ m_gnd_offset*/; }
// inline void ground_level_offset(double o) { m_gnd_offset = o; }
// inline double ground_level_offset() const { return m_gnd_offset; }
const std::vector<Vec3f>& vertices() const; const std::vector<Vec3f>& vertices() const;
const std::vector<Vec3i>& indices() const; const std::vector<Vec3i>& indices() const;
const Vec3f& vertices(size_t idx) const; const Vec3f& vertices(size_t idx) const;

View File

@ -386,7 +386,7 @@ public:
bool force_neutral_color : 1; bool force_neutral_color : 1;
// Whether or not to force rendering of sinking contours // Whether or not to force rendering of sinking contours
bool force_sinking_contours : 1; bool force_sinking_contours : 1;
}; }; // this gets instantiated automatically in the parent struct
// Is mouse or rectangle selection over this object to select/deselect it ? // Is mouse or rectangle selection over this object to select/deselect it ?
EHoverState hover; EHoverState hover;

View File

@ -2188,6 +2188,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
} }
} }
} }
if (printer_technology == ptSLA) { if (printer_technology == ptSLA) {
// size_t idx = 0; // size_t idx = 0;
// const SLAPrint *sla_print = this->sla_print(); // const SLAPrint *sla_print = this->sla_print();
@ -3846,7 +3847,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
#else #else
model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
else if (selection_mode == Selection::Volume) else if (volume_idx >= 0 && selection_mode == Selection::Volume)
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation()); model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
#else #else
@ -4020,7 +4021,7 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
} }
else if (selection_mode == Selection::Volume) { else if (selection_mode == Selection::Volume && volume_idx >= 0) {
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation()); model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation()); model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());

View File

@ -688,6 +688,8 @@ public:
void set_raycaster_gizmos_on_top(bool value) { void set_raycaster_gizmos_on_top(bool value) {
m_scene_raycaster.set_gizmos_on_top(value); m_scene_raycaster.set_gizmos_on_top(value);
} }
const SceneRaycaster & raycaster() const { return m_scene_raycaster; }
#endif // ENABLE_RAYCAST_PICKING #endif // ENABLE_RAYCAST_PICKING
void set_as_dirty(); void set_as_dirty();

View File

@ -44,7 +44,6 @@ static bool is_improper_category(const std::string& category, const int extruder
(!is_object_settings && category == "Support material"); (!is_object_settings && category == "Support material");
} }
//------------------------------------- //-------------------------------------
// SettingsFactory // SettingsFactory
//------------------------------------- //-------------------------------------
@ -155,14 +154,14 @@ wxBitmapBundle* SettingsFactory::get_category_bitmap(const std::string& category
//------------------------------------- //-------------------------------------
// Note: id accords to type of the sub-object (adding volume), so sequence of the menu items is important // Note: id accords to type of the sub-object (adding volume), so sequence of the menu items is important
const std::vector<std::pair<std::string, std::string>> MenuFactory::ADD_VOLUME_MENU_ITEMS { static const constexpr std::array<std::pair<const char *, const char *>, 5> ADD_VOLUME_MENU_ITEMS = {{
// menu_item Name menu_item bitmap name // menu_item Name menu_item bitmap name
{L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART {L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART
{L("Add negative volume"), "add_negative" }, // ~ModelVolumeType::NEGATIVE_VOLUME {L("Add negative volume"), "add_negative" }, // ~ModelVolumeType::NEGATIVE_VOLUME
{L("Add modifier"), "add_modifier"}, // ~ModelVolumeType::PARAMETER_MODIFIER {L("Add modifier"), "add_modifier"}, // ~ModelVolumeType::PARAMETER_MODIFIER
{L("Add support blocker"), "support_blocker"}, // ~ModelVolumeType::SUPPORT_BLOCKER {L("Add support blocker"), "support_blocker"}, // ~ModelVolumeType::SUPPORT_BLOCKER
{L("Add support enforcer"), "support_enforcer"}, // ~ModelVolumeType::SUPPORT_ENFORCER {L("Add support enforcer"), "support_enforcer"}, // ~ModelVolumeType::SUPPORT_ENFORCER
}; }};
// Note: id accords to type of the sub-object (adding volume), so sequence of the menu items is important // Note: id accords to type of the sub-object (adding volume), so sequence of the menu items is important
const std::vector<std::pair<std::string, std::string>> MenuFactory::TEXT_VOLUME_ICONS { const std::vector<std::pair<std::string, std::string>> MenuFactory::TEXT_VOLUME_ICONS {
@ -583,6 +582,55 @@ void MenuFactory::append_menu_items_add_volume(wxMenu* menu)
append_menu_item_layers_editing(menu); append_menu_item_layers_editing(menu);
} }
void MenuFactory::append_menu_items_add_sla_volume(wxMenu *menu)
{
// Update "add" items(delete old & create new) settings popupmenu
for (auto& item : ADD_VOLUME_MENU_ITEMS) {
const auto settings_id = menu->FindItem(_(item.first));
if (settings_id != wxNOT_FOUND)
menu->Destroy(settings_id);
}
const ConfigOptionMode mode = wxGetApp().get_mode();
if (mode == comAdvanced) {
append_menu_item(menu, wxID_ANY, _(ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART)].first), "",
[](wxCommandEvent&) { obj_list()->load_subobject(ModelVolumeType::MODEL_PART); },
ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART)].second, nullptr,
[]() { return obj_list()->is_instance_or_object_selected(); }, m_parent);
} else {
auto& item = ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART)];
wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType::MODEL_PART);
append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second,
[]() { return obj_list()->is_instance_or_object_selected(); }, m_parent);
}
{
auto& item = ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::NEGATIVE_VOLUME)];
wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType::NEGATIVE_VOLUME);
append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second,
[]() { return obj_list()->is_instance_or_object_selected(); }, m_parent);
}
{
auto& item = ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_ENFORCER)];
wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType::SUPPORT_ENFORCER);
append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second,
[]() { return obj_list()->is_instance_or_object_selected(); }, m_parent);
}
{
auto& item = ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_BLOCKER)];
wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType::SUPPORT_BLOCKER);
append_submenu(menu, sub_menu, wxID_ANY, _(item.first), "", item.second,
[]() { return obj_list()->is_instance_or_object_selected(); }, m_parent);
}
}
wxMenuItem* MenuFactory::append_menu_item_layers_editing(wxMenu* menu) wxMenuItem* MenuFactory::append_menu_item_layers_editing(wxMenu* menu)
{ {
return append_menu_item(menu, wxID_ANY, _L("Height range Modifier"), "", return append_menu_item(menu, wxID_ANY, _L("Height range Modifier"), "",
@ -631,7 +679,7 @@ wxMenuItem* MenuFactory::append_menu_item_settings(wxMenu* menu_)
// If there are selected more then one instance but not all of them // If there are selected more then one instance but not all of them
// don't add settings menu items // don't add settings menu items
const Selection& selection = get_selection(); const Selection& selection = get_selection();
if ((selection.is_multiple_full_instance() && !selection.is_single_full_object()) || if ((selection.is_multiple_full_instance() && !selection.is_single_full_object()) || (printer_technology() == ptSLA && selection.is_single_volume()) ||
selection.is_multiple_volume() || selection.is_mixed()) // more than one volume(part) is selected on the scene selection.is_multiple_volume() || selection.is_mixed()) // more than one volume(part) is selected on the scene
return nullptr; return nullptr;
@ -1066,6 +1114,8 @@ void MenuFactory::create_sla_object_menu()
[]() { return plater()->can_split(true); }, m_parent); []() { return plater()->can_split(true); }, m_parent);
m_sla_object_menu.AppendSeparator(); m_sla_object_menu.AppendSeparator();
append_menu_items_add_sla_volume(&m_sla_object_menu);
m_sla_object_menu.AppendSeparator();
} }
void MenuFactory::append_immutable_part_menu_items(wxMenu* menu) void MenuFactory::append_immutable_part_menu_items(wxMenu* menu)

View File

@ -92,6 +92,7 @@ private:
wxMenu* append_submenu_add_generic(wxMenu* menu, ModelVolumeType type); wxMenu* append_submenu_add_generic(wxMenu* menu, ModelVolumeType type);
void append_menu_item_add_text(wxMenu* menu, ModelVolumeType type, bool is_submenu_item = true); void append_menu_item_add_text(wxMenu* menu, ModelVolumeType type, bool is_submenu_item = true);
void append_menu_items_add_volume(wxMenu* menu); void append_menu_items_add_volume(wxMenu* menu);
void append_menu_items_add_sla_volume(wxMenu* menu);
wxMenuItem* append_menu_item_layers_editing(wxMenu* menu); wxMenuItem* append_menu_item_layers_editing(wxMenu* menu);
wxMenuItem* append_menu_item_settings(wxMenu* menu); wxMenuItem* append_menu_item_settings(wxMenu* menu);
wxMenuItem* append_menu_item_change_type(wxMenu* menu); wxMenuItem* append_menu_item_change_type(wxMenu* menu);

View File

@ -53,8 +53,8 @@ void GLGizmoHollow::data_changed()
reload_cache(); reload_cache();
m_old_mo_id = mo->id(); m_old_mo_id = mo->id();
} }
if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh()) // if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh())
m_holes_in_drilled_mesh = mo->sla_drain_holes; // m_holes_in_drilled_mesh = mo->sla_drain_holes;
#if ENABLE_RAYCAST_PICKING #if ENABLE_RAYCAST_PICKING
if (m_raycasters.empty()) if (m_raycasters.empty())
on_register_raycasters_for_picking(); on_register_raycasters_for_picking();
@ -206,11 +206,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
#endif // !ENABLE_RAYCAST_PICKING #endif // !ENABLE_RAYCAST_PICKING
if (size_t(m_hover_id) == i) if (size_t(m_hover_id) == i)
render_color = ColorRGBA::CYAN(); render_color = ColorRGBA::CYAN();
else if (m_c->hollowed_mesh() && // else if (m_c->hollowed_mesh() &&
i < m_c->hollowed_mesh()->get_drainholes().size() && // i < m_c->hollowed_mesh()->get_drainholes().size() &&
m_c->hollowed_mesh()->get_drainholes()[i].failed) { // m_c->hollowed_mesh()->get_drainholes()[i].failed) {
render_color = { 1.0f, 0.0f, 0.0f, 0.5f }; // render_color = { 1.0f, 0.0f, 0.0f, 0.5f };
} // }
else else
render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f);
#if !ENABLE_RAYCAST_PICKING #if !ENABLE_RAYCAST_PICKING
@ -314,18 +314,18 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, V
normal, normal,
clp_dist != 0. ? clp : nullptr)) clp_dist != 0. ? clp : nullptr))
{ {
if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh()) { // if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh()) {
// in this case the raycaster sees the hollowed and drilled mesh. // // in this case the raycaster sees the hollowed and drilled mesh.
// if the point lies on the surface created by the hole, we want // // if the point lies on the surface created by the hole, we want
// to ignore it. // // to ignore it.
for (const sla::DrainHole& hole : m_holes_in_drilled_mesh) { // for (const sla::DrainHole& hole : m_holes_in_drilled_mesh) {
sla::DrainHole outer(hole); // sla::DrainHole outer(hole);
outer.radius *= 1.001f; // outer.radius *= 1.001f;
outer.height *= 1.001f; // outer.height *= 1.001f;
if (outer.is_inside(hit)) // if (outer.is_inside(hit))
return false; // return false;
} // }
} // }
// Return both the point and the facet normal. // Return both the point and the facet normal.
pos_and_normal = std::make_pair(hit, normal); pos_and_normal = std::make_pair(hit, normal);

View File

@ -86,6 +86,8 @@ void GLGizmoSlaSupports::data_changed()
update_raycasters_for_picking_transform(); update_raycasters_for_picking_transform();
#endif // ENABLE_RAYCAST_PICKING #endif // ENABLE_RAYCAST_PICKING
} }
// m_parent.toggle_model_objects_visibility(false);
} }
@ -179,8 +181,8 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
const size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size(); const size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size();
const bool has_points = (cache_size != 0); const bool has_points = (cache_size != 0);
const bool has_holes = (! m_c->hollowed_mesh()->get_hollowed_mesh() const bool has_holes = (/*! m_c->hollowed_mesh()->get_hollowed_mesh()
&& ! m_c->selection_info()->model_object()->sla_drain_holes.empty()); &&*/ ! m_c->selection_info()->model_object()->sla_drain_holes.empty());
if (! has_points && ! has_holes) if (! has_points && ! has_holes)
return; return;
@ -304,7 +306,8 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
if (m_editing_mode) { if (m_editing_mode) {
// in case the normal is not yet cached, find and cache it // in case the normal is not yet cached, find and cache it
if (m_editing_cache[i].normal == Vec3f::Zero()) if (m_editing_cache[i].normal == Vec3f::Zero())
m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal); m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
//m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
Eigen::Quaterniond q; Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>()); q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
@ -453,7 +456,7 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
// Return false if no intersection was found, true otherwise. // Return false if no intersection was found, true otherwise.
bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal) bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal)
{ {
if (! m_c->raycaster()->raycaster()) if (m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->empty())
return false; return false;
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
@ -468,7 +471,7 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec
// The raycaster query // The raycaster query
Vec3f hit; Vec3f hit;
Vec3f normal; Vec3f normal;
if (m_c->raycaster()->raycaster()->unproject_on_mesh( if (m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->unproject_on_mesh(
mouse_pos, mouse_pos,
trafo.get_matrix(), trafo.get_matrix(),
camera, camera,
@ -477,24 +480,24 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec
clp_dist != 0. ? clp : nullptr)) clp_dist != 0. ? clp : nullptr))
{ {
// Check whether the hit is in a hole // Check whether the hit is in a hole
bool in_hole = false; // bool in_hole = false;
// In case the hollowed and drilled mesh is available, we can allow // In case the hollowed and drilled mesh is available, we can allow
// placing points in holes, because they should never end up // placing points in holes, because they should never end up
// on surface that's been drilled away. // on surface that's been drilled away.
if (! m_c->hollowed_mesh()->get_hollowed_mesh()) { // if (! m_c->hollowed_mesh()->get_hollowed_mesh()) {
sla::DrainHoles drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; // sla::DrainHoles drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
for (const sla::DrainHole& hole : drain_holes) { // for (const sla::DrainHole& hole : drain_holes) {
if (hole.is_inside(hit)) { // if (hole.is_inside(hit)) {
in_hole = true; // in_hole = true;
break; // break;
} // }
} // }
} // }
if (! in_hole) { // if (! in_hole) {
// Return both the point and the facet normal. // Return both the point and the facet normal.
pos_and_normal = std::make_pair(hit, normal); pos_and_normal = std::make_pair(hit, normal);
return true; return true;
} // }
} }
return false; return false;
@ -589,7 +592,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
for (size_t idx : points_idxs) for (size_t idx : points_idxs)
points_inside.emplace_back((trafo.get_matrix().cast<float>() * (m_editing_cache[idx].support_point.pos + m_editing_cache[idx].normal)).cast<float>()); points_inside.emplace_back((trafo.get_matrix().cast<float>() * (m_editing_cache[idx].support_point.pos + m_editing_cache[idx].normal)).cast<float>());
for (size_t idx : m_c->raycaster()->raycaster()->get_unobscured_idxs( assert(!m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume).emtpy());
for (size_t idx : m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->get_unobscured_idxs(
trafo, wxGetApp().plater()->get_camera(), points_inside, trafo, wxGetApp().plater()->get_camera(), points_inside,
m_c->object_clipper()->get_clipping_plane())) m_c->object_clipper()->get_clipping_plane()))
{ {
@ -1457,7 +1461,7 @@ void GLGizmoSlaSupports::update_raycasters_for_picking_transform()
const Transform3d support_matrix = Geometry::translation_transform(m_editing_cache[i].support_point.pos.cast<double>()) * instance_scaling_matrix_inverse; const Transform3d support_matrix = Geometry::translation_transform(m_editing_cache[i].support_point.pos.cast<double>()) * instance_scaling_matrix_inverse;
if (m_editing_cache[i].normal == Vec3f::Zero()) if (m_editing_cache[i].normal == Vec3f::Zero())
m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal); m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
Eigen::Quaterniond q; Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>()); q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());

View File

@ -25,7 +25,7 @@ private:
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal); bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
const float RenderPointScale = 1.f; static constexpr float RenderPointScale = 1.f;
class CacheEntry { class CacheEntry {
public: public:

View File

@ -23,7 +23,7 @@ CommonGizmosDataPool::CommonGizmosDataPool(GLCanvas3D* canvas)
using c = CommonGizmosDataID; using c = CommonGizmosDataID;
m_data[c::SelectionInfo].reset( new SelectionInfo(this)); m_data[c::SelectionInfo].reset( new SelectionInfo(this));
m_data[c::InstancesHider].reset( new InstancesHider(this)); m_data[c::InstancesHider].reset( new InstancesHider(this));
m_data[c::HollowedMesh].reset( new HollowedMesh(this)); // m_data[c::HollowedMesh].reset( new HollowedMesh(this));
m_data[c::Raycaster].reset( new Raycaster(this)); m_data[c::Raycaster].reset( new Raycaster(this));
m_data[c::ObjectClipper].reset( new ObjectClipper(this)); m_data[c::ObjectClipper].reset( new ObjectClipper(this));
m_data[c::SupportsClipper].reset( new SupportsClipper(this)); m_data[c::SupportsClipper].reset( new SupportsClipper(this));
@ -59,12 +59,12 @@ InstancesHider* CommonGizmosDataPool::instances_hider() const
return inst_hider->is_valid() ? inst_hider : nullptr; return inst_hider->is_valid() ? inst_hider : nullptr;
} }
HollowedMesh* CommonGizmosDataPool::hollowed_mesh() const //HollowedMesh* CommonGizmosDataPool::hollowed_mesh() const
{ //{
HollowedMesh* hol_mesh = dynamic_cast<HollowedMesh*>(m_data.at(CommonGizmosDataID::HollowedMesh).get()); // HollowedMesh* hol_mesh = dynamic_cast<HollowedMesh*>(m_data.at(CommonGizmosDataID::HollowedMesh).get());
assert(hol_mesh); // assert(hol_mesh);
return hol_mesh->is_valid() ? hol_mesh : nullptr; // return hol_mesh->is_valid() ? hol_mesh : nullptr;
} //}
Raycaster* CommonGizmosDataPool::raycaster() const Raycaster* CommonGizmosDataPool::raycaster() const
{ {
@ -117,16 +117,18 @@ bool CommonGizmosDataPool::check_dependencies(CommonGizmosDataID required) const
void SelectionInfo::on_update() void SelectionInfo::on_update()
{ {
const Selection& selection = get_pool()->get_canvas()->get_selection(); const Selection& selection = get_pool()->get_canvas()->get_selection();
m_model_object = nullptr;
m_print_object = nullptr;
if (selection.is_single_full_instance()) { if (selection.is_single_full_instance()) {
m_model_object = selection.get_model()->objects[selection.get_object_idx()]; m_model_object = selection.get_model()->objects[selection.get_object_idx()];
m_model_volume = nullptr;
if (m_model_object)
m_print_object = get_pool()->get_canvas()->sla_print()->get_object(m_model_object->id());
m_z_shift = selection.get_first_volume()->get_sla_shift_z(); m_z_shift = selection.get_first_volume()->get_sla_shift_z();
} }
else {
m_model_object = nullptr;
if (selection.is_single_volume())
m_model_volume = selection.get_model()->objects[selection.get_object_idx()]->volumes[selection.get_first_volume()->volume_idx()];
}
} }
void SelectionInfo::on_release() void SelectionInfo::on_release()
@ -253,78 +255,78 @@ void InstancesHider::render_cut() const
void HollowedMesh::on_update() //void HollowedMesh::on_update()
{ //{
const ModelObject* mo = get_pool()->selection_info()->model_object(); // const ModelObject* mo = get_pool()->selection_info()->model_object();
bool is_sla = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA; // bool is_sla = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA;
if (! mo || ! is_sla) // if (! mo || ! is_sla)
return; // return;
const GLCanvas3D* canvas = get_pool()->get_canvas(); // const GLCanvas3D* canvas = get_pool()->get_canvas();
const PrintObjects& print_objects = canvas->sla_print()->objects(); // const PrintObjects& print_objects = canvas->sla_print()->objects();
const SLAPrintObject* print_object = (m_print_object_idx >= 0 && m_print_object_idx < int(print_objects.size())) // const SLAPrintObject* print_object = (m_print_object_idx >= 0 && m_print_object_idx < int(print_objects.size()))
? print_objects[m_print_object_idx] // ? print_objects[m_print_object_idx]
: nullptr; // : nullptr;
// Find the respective SLAPrintObject. // // Find the respective SLAPrintObject.
if (m_print_object_idx < 0 || m_print_objects_count != int(print_objects.size())) { // if (m_print_object_idx < 0 || m_print_objects_count != int(print_objects.size())) {
m_print_objects_count = print_objects.size(); // m_print_objects_count = print_objects.size();
m_print_object_idx = -1; // m_print_object_idx = -1;
for (const SLAPrintObject* po : print_objects) { // for (const SLAPrintObject* po : print_objects) {
++m_print_object_idx; // ++m_print_object_idx;
if (po->model_object()->id() == mo->id()) { // if (po->model_object()->id() == mo->id()) {
print_object = po; // print_object = po;
break; // break;
} // }
} // }
} // }
// If there is a valid SLAPrintObject, check state of Hollowing step. // // If there is a valid SLAPrintObject, check state of Hollowing step.
if (print_object) { // if (print_object) {
if (print_object->is_step_done(slaposDrillHoles) && !print_object->get_mesh_to_print().empty()) { // if (print_object->is_step_done(slaposDrillHoles) && !print_object->get_mesh_to_print().empty()) {
size_t timestamp = print_object->step_state_with_timestamp(slaposDrillHoles).timestamp; // size_t timestamp = print_object->step_state_with_timestamp(slaposDrillHoles).timestamp;
if (timestamp > m_old_hollowing_timestamp) { // if (timestamp > m_old_hollowing_timestamp) {
const TriangleMesh& backend_mesh = print_object->get_mesh_to_print(); // const TriangleMesh& backend_mesh = print_object->get_mesh_to_print();
if (! backend_mesh.empty()) { // if (! backend_mesh.empty()) {
m_hollowed_mesh_transformed.reset(new TriangleMesh(backend_mesh)); // m_hollowed_mesh_transformed.reset(new TriangleMesh(backend_mesh));
Transform3d trafo_inv = (canvas->sla_print()->sla_trafo(*mo) * print_object->model_object()->volumes.front()->get_transformation().get_matrix()).inverse(); // Transform3d trafo_inv = (canvas->sla_print()->sla_trafo(*mo) * print_object->model_object()->volumes.front()->get_transformation().get_matrix()).inverse();
m_hollowed_mesh_transformed->transform(trafo_inv); // m_hollowed_mesh_transformed->transform(trafo_inv);
m_drainholes = print_object->model_object()->sla_drain_holes; // m_drainholes = print_object->model_object()->sla_drain_holes;
m_old_hollowing_timestamp = timestamp; // m_old_hollowing_timestamp = timestamp;
// indexed_triangle_set interior = print_object->hollowed_interior_mesh(); //// indexed_triangle_set interior = print_object->hollowed_interior_mesh();
// its_flip_triangles(interior); //// its_flip_triangles(interior);
// m_hollowed_interior_transformed = std::make_unique<TriangleMesh>(std::move(interior)); //// m_hollowed_interior_transformed = std::make_unique<TriangleMesh>(std::move(interior));
// m_hollowed_interior_transformed->transform(trafo_inv); //// m_hollowed_interior_transformed->transform(trafo_inv);
} // }
else { // else {
m_hollowed_mesh_transformed.reset(nullptr); // m_hollowed_mesh_transformed.reset(nullptr);
} // }
} // }
} // }
else // else
m_hollowed_mesh_transformed.reset(nullptr); // m_hollowed_mesh_transformed.reset(nullptr);
} // }
} //}
void HollowedMesh::on_release() //void HollowedMesh::on_release()
{ //{
m_hollowed_mesh_transformed.reset(); // m_hollowed_mesh_transformed.reset();
m_old_hollowing_timestamp = 0; // m_old_hollowing_timestamp = 0;
m_print_object_idx = -1; // m_print_object_idx = -1;
} //}
const TriangleMesh* HollowedMesh::get_hollowed_mesh() const //const TriangleMesh* HollowedMesh::get_hollowed_mesh() const
{ //{
return m_hollowed_mesh_transformed.get(); // return m_hollowed_mesh_transformed.get();
} //}
const TriangleMesh* HollowedMesh::get_hollowed_interior() const //const TriangleMesh* HollowedMesh::get_hollowed_interior() const
{ //{
return m_hollowed_interior_transformed.get(); // return m_hollowed_interior_transformed.get();
} //}
@ -345,12 +347,13 @@ void Raycaster::on_update()
mvs = mo->volumes; mvs = mo->volumes;
std::vector<const TriangleMesh*> meshes; std::vector<const TriangleMesh*> meshes;
if (mvs.size() == 1) { const std::vector<ModelVolume*>& mvs = mo->volumes;
assert(mvs.front()->is_model_part()); // if (mvs.size() == 1) {
const HollowedMesh* hollowed_mesh_tracker = get_pool()->hollowed_mesh(); // assert(mvs.front()->is_model_part());
if (hollowed_mesh_tracker && hollowed_mesh_tracker->get_hollowed_mesh()) // const HollowedMesh* hollowed_mesh_tracker = get_pool()->hollowed_mesh();
meshes.push_back(hollowed_mesh_tracker->get_hollowed_mesh()); // if (hollowed_mesh_tracker && hollowed_mesh_tracker->get_hollowed_mesh())
} // meshes.push_back(hollowed_mesh_tracker->get_hollowed_mesh());
// }
if (meshes.empty()) { if (meshes.empty()) {
for (const ModelVolume* v : mvs) { for (const ModelVolume* v : mvs) {
if (v->is_model_part()) if (v->is_model_part())
@ -396,9 +399,9 @@ void ObjectClipper::on_update()
// which mesh should be cut? // which mesh should be cut?
std::vector<const TriangleMesh*> meshes; std::vector<const TriangleMesh*> meshes;
bool has_hollowed = get_pool()->hollowed_mesh() && get_pool()->hollowed_mesh()->get_hollowed_mesh(); // bool has_hollowed = get_pool()->hollowed_mesh() && get_pool()->hollowed_mesh()->get_hollowed_mesh();
if (has_hollowed) // if (has_hollowed)
meshes.push_back(get_pool()->hollowed_mesh()->get_hollowed_mesh()); // meshes.push_back(get_pool()->hollowed_mesh()->get_hollowed_mesh());
if (meshes.empty()) if (meshes.empty())
for (const ModelVolume* mv : mo->volumes) for (const ModelVolume* mv : mo->volumes)
@ -412,8 +415,8 @@ void ObjectClipper::on_update()
} }
m_old_meshes = meshes; m_old_meshes = meshes;
if (has_hollowed) // if (has_hollowed)
m_clippers.front()->set_negative_mesh(*get_pool()->hollowed_mesh()->get_hollowed_interior()); // m_clippers.front()->set_negative_mesh(*get_pool()->hollowed_mesh()->get_hollowed_interior());
m_active_inst_bb_radius = m_active_inst_bb_radius =
mo->instance_bounding_box(get_pool()->selection_info()->get_active_instance()).radius(); mo->instance_bounding_box(get_pool()->selection_info()->get_active_instance()).radius();

View File

@ -5,11 +5,11 @@
#include <map> #include <map>
#include "slic3r/GUI/MeshUtils.hpp" #include "slic3r/GUI/MeshUtils.hpp"
#include "libslic3r/SLA/Hollowing.hpp"
namespace Slic3r { namespace Slic3r {
class ModelObject; class ModelObject;
class SLAPrintObject;
class ModelVolume; class ModelVolume;
namespace GUI { namespace GUI {
@ -85,7 +85,7 @@ public:
// Getters for the data that need to be accessed from the gizmos directly. // Getters for the data that need to be accessed from the gizmos directly.
CommonGizmosDataObjects::SelectionInfo* selection_info() const; CommonGizmosDataObjects::SelectionInfo* selection_info() const;
CommonGizmosDataObjects::InstancesHider* instances_hider() const; CommonGizmosDataObjects::InstancesHider* instances_hider() const;
CommonGizmosDataObjects::HollowedMesh* hollowed_mesh() const; // CommonGizmosDataObjects::HollowedMesh* hollowed_mesh() const;
CommonGizmosDataObjects::Raycaster* raycaster() const; CommonGizmosDataObjects::Raycaster* raycaster() const;
CommonGizmosDataObjects::ObjectClipper* object_clipper() const; CommonGizmosDataObjects::ObjectClipper* object_clipper() const;
CommonGizmosDataObjects::SupportsClipper* supports_clipper() const; CommonGizmosDataObjects::SupportsClipper* supports_clipper() const;
@ -158,6 +158,7 @@ public:
// Returns a non-null pointer if the selection is a single full instance // Returns a non-null pointer if the selection is a single full instance
ModelObject* model_object() const { return m_model_object; } ModelObject* model_object() const { return m_model_object; }
const SLAPrintObject *print_object() const { return m_print_object; }
// Returns a non-null pointer if the selection is a single volume // Returns a non-null pointer if the selection is a single volume
ModelVolume* model_volume() const { return m_model_volume; } ModelVolume* model_volume() const { return m_model_volume; }
int get_active_instance() const; int get_active_instance() const;
@ -169,6 +170,7 @@ protected:
private: private:
ModelObject* m_model_object = nullptr; ModelObject* m_model_object = nullptr;
const SLAPrintObject *m_print_object = nullptr;
ModelVolume* m_model_volume = nullptr; ModelVolume* m_model_volume = nullptr;
// int m_active_inst = -1; // int m_active_inst = -1;
float m_z_shift = 0.f; float m_z_shift = 0.f;
@ -201,32 +203,32 @@ private:
class HollowedMesh : public CommonGizmosDataBase //class HollowedMesh : public CommonGizmosDataBase
{ //{
public: //public:
explicit HollowedMesh(CommonGizmosDataPool* cgdp) // explicit HollowedMesh(CommonGizmosDataPool* cgdp)
: CommonGizmosDataBase(cgdp) {} // : CommonGizmosDataBase(cgdp) {}
#ifndef NDEBUG //#ifndef NDEBUG
CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; } // CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; }
#endif // NDEBUG //#endif // NDEBUG
const sla::DrainHoles &get_drainholes() const { return m_drainholes; } // const sla::DrainHoles &get_drainholes() const { return m_drainholes; }
const TriangleMesh* get_hollowed_mesh() const; // const TriangleMesh* get_hollowed_mesh() const;
const TriangleMesh* get_hollowed_interior() const; // const TriangleMesh* get_hollowed_interior() const;
protected: //protected:
void on_update() override; // void on_update() override;
void on_release() override; // void on_release() override;
private: //private:
std::unique_ptr<TriangleMesh> m_hollowed_mesh_transformed; // std::unique_ptr<TriangleMesh> m_hollowed_mesh_transformed;
std::unique_ptr<TriangleMesh> m_hollowed_interior_transformed; // std::unique_ptr<TriangleMesh> m_hollowed_interior_transformed;
size_t m_old_hollowing_timestamp = 0; // size_t m_old_hollowing_timestamp = 0;
int m_print_object_idx = -1; // int m_print_object_idx = -1;
int m_print_objects_count = 0; // int m_print_objects_count = 0;
sla::DrainHoles m_drainholes; // sla::DrainHoles m_drainholes;
}; //};

View File

@ -2649,17 +2649,6 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
model_object->ensure_on_bed(is_project_file); model_object->ensure_on_bed(is_project_file);
} }
// check multi-part object adding for the SLA-printing
if (printer_technology == ptSLA) {
for (auto obj : model.objects)
if ( obj->volumes.size()>1 ) {
Slic3r::GUI::show_error(nullptr,
format_wxstr(_L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part"),
from_path(filename)));
return obj_idxs;
}
}
if (one_by_one) { if (one_by_one) {
if ((type_3mf && !is_project_file) || (type_any_amf && !type_zip_amf)) if ((type_3mf && !is_project_file) || (type_any_amf && !type_zip_amf))
model.center_instances_around_point(this->bed.build_volume().bed_center()); model.center_instances_around_point(this->bed.build_volume().bed_center());

View File

@ -88,7 +88,7 @@ void SceneRaycaster::remove_raycaster(std::shared_ptr<SceneRaycasterItem> item)
} }
} }
SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane) SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane) const
{ {
double closest_hit_squared_distance = std::numeric_limits<double>::max(); double closest_hit_squared_distance = std::numeric_limits<double>::max();
auto is_closest = [&closest_hit_squared_distance](const Camera& camera, const Vec3f& hit) { auto is_closest = [&closest_hit_squared_distance](const Camera& camera, const Vec3f& hit) {
@ -107,7 +107,7 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came
auto test_raycasters = [this, is_closest, clipping_plane](EType type, const Vec2d& mouse_pos, const Camera& camera, HitResult& ret) { auto test_raycasters = [this, is_closest, clipping_plane](EType type, const Vec2d& mouse_pos, const Camera& camera, HitResult& ret) {
const ClippingPlane* clip_plane = (clipping_plane != nullptr && type == EType::Volume) ? clipping_plane : nullptr; const ClippingPlane* clip_plane = (clipping_plane != nullptr && type == EType::Volume) ? clipping_plane : nullptr;
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters(type); const std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters(type);
const Vec3f camera_forward = camera.get_dir_forward().cast<float>(); const Vec3f camera_forward = camera.get_dir_forward().cast<float>();
HitResult current_hit = { type }; HitResult current_hit = { type };
for (std::shared_ptr<SceneRaycasterItem> item : *raycasters) { for (std::shared_ptr<SceneRaycasterItem> item : *raycasters) {
@ -214,6 +214,20 @@ std::vector<std::shared_ptr<SceneRaycasterItem>>* SceneRaycaster::get_raycasters
return ret; return ret;
} }
const std::vector<std::shared_ptr<SceneRaycasterItem>>* SceneRaycaster::get_raycasters(EType type) const
{
const std::vector<std::shared_ptr<SceneRaycasterItem>>* ret = nullptr;
switch (type)
{
case EType::Bed: { ret = &m_bed; break; }
case EType::Volume: { ret = &m_volumes; break; }
case EType::Gizmo: { ret = &m_gizmos; break; }
default: { break; }
}
assert(ret != nullptr);
return ret;
}
int SceneRaycaster::base_id(EType type) int SceneRaycaster::base_id(EType type)
{ {
switch (type) switch (type)

View File

@ -89,10 +89,11 @@ public:
void remove_raycaster(std::shared_ptr<SceneRaycasterItem> item); void remove_raycaster(std::shared_ptr<SceneRaycasterItem> item);
std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters(EType type); std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters(EType type);
const std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters(EType type) const;
void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; } void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; }
HitResult hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane = nullptr); HitResult hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane = nullptr) const;
#if ENABLE_RAYCAST_PICKING_DEBUG #if ENABLE_RAYCAST_PICKING_DEBUG
void render_hit(const Camera& camera); void render_hit(const Camera& camera);

View File

@ -62,18 +62,18 @@ Selection::VolumeCache::VolumeCache(const Geometry::Transformation& volume_trans
bool Selection::Clipboard::is_sla_compliant() const bool Selection::Clipboard::is_sla_compliant() const
{ {
if (m_mode == Selection::Volume) // if (m_mode == Selection::Volume)
return false; // return false;
for (const ModelObject* o : m_model->objects) { // for (const ModelObject* o : m_model->objects) {
if (o->is_multiparts()) // if (o->is_multiparts())
return false; // return false;
for (const ModelVolume* v : o->volumes) { // for (const ModelVolume* v : o->volumes) {
if (v->is_modifier()) // if (v->is_modifier())
return false; // return false;
} // }
} // }
return true; return true;
} }
@ -571,13 +571,13 @@ bool Selection::is_from_single_object() const
bool Selection::is_sla_compliant() const bool Selection::is_sla_compliant() const
{ {
if (m_mode == Volume) // if (m_mode == Volume)
return false; // return false;
for (unsigned int i : m_list) { // for (unsigned int i : m_list) {
if ((*m_volumes)[i]->is_modifier) // if ((*m_volumes)[i]->is_modifier)
return false; // return false;
} // }
return true; return true;
} }

View File

@ -3279,9 +3279,9 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/,
const PresetWithVendorProfile new_printer_preset_with_vendor_profile = m_presets->get_preset_with_vendor_profile(new_printer_preset); const PresetWithVendorProfile new_printer_preset_with_vendor_profile = m_presets->get_preset_with_vendor_profile(new_printer_preset);
PrinterTechnology old_printer_technology = m_presets->get_edited_preset().printer_technology(); PrinterTechnology old_printer_technology = m_presets->get_edited_preset().printer_technology();
PrinterTechnology new_printer_technology = new_printer_preset.printer_technology(); PrinterTechnology new_printer_technology = new_printer_preset.printer_technology();
if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !wxGetApp().may_switch_to_SLA_preset(_L("New printer preset selected"))) /*if (new_printer_technology == ptSLA && old_printer_technology == ptFFF && !wxGetApp().may_switch_to_SLA_preset(_L("New printer preset selected")))
canceled = true; canceled = true;
else { else */{
struct PresetUpdate { struct PresetUpdate {
Preset::Type tab_type; Preset::Type tab_type;
PresetCollection *presets; PresetCollection *presets;