mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 02:49:04 +08:00
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:
parent
15fa4c42d6
commit
9bc3410474
@ -28,7 +28,6 @@ class AABBMesh {
|
||||
class AABBImpl;
|
||||
|
||||
const indexed_triangle_set* m_tm;
|
||||
// double m_ground_level = 0/*, m_gnd_offset = 0*/;
|
||||
|
||||
std::unique_ptr<AABBImpl> m_aabb;
|
||||
VertexFaceIndex m_vfidx; // vertex-face index
|
||||
@ -57,10 +56,6 @@ public:
|
||||
|
||||
~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<Vec3i>& indices() const;
|
||||
const Vec3f& vertices(size_t idx) const;
|
||||
|
@ -386,7 +386,7 @@ public:
|
||||
bool force_neutral_color : 1;
|
||||
// Whether or not to force rendering of sinking contours
|
||||
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 ?
|
||||
EHoverState hover;
|
||||
|
@ -2188,6 +2188,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (printer_technology == ptSLA) {
|
||||
// size_t idx = 0;
|
||||
// const SLAPrint *sla_print = this->sla_print();
|
||||
@ -3846,7 +3847,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
#else
|
||||
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
else if (selection_mode == Selection::Volume)
|
||||
else if (volume_idx >= 0 && selection_mode == Selection::Volume)
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||
#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());
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
else if (selection_mode == Selection::Volume) {
|
||||
else if (selection_mode == Selection::Volume && volume_idx >= 0) {
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
||||
|
@ -688,6 +688,8 @@ public:
|
||||
void set_raycaster_gizmos_on_top(bool value) {
|
||||
m_scene_raycaster.set_gizmos_on_top(value);
|
||||
}
|
||||
|
||||
const SceneRaycaster & raycaster() const { return m_scene_raycaster; }
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void set_as_dirty();
|
||||
|
@ -44,7 +44,6 @@ static bool is_improper_category(const std::string& category, const int extruder
|
||||
(!is_object_settings && category == "Support material");
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------
|
||||
// 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
|
||||
const std::vector<std::pair<std::string, std::string>> MenuFactory::ADD_VOLUME_MENU_ITEMS {
|
||||
// menu_item Name menu_item bitmap name
|
||||
{L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART
|
||||
{L("Add negative volume"), "add_negative" }, // ~ModelVolumeType::NEGATIVE_VOLUME
|
||||
{L("Add modifier"), "add_modifier"}, // ~ModelVolumeType::PARAMETER_MODIFIER
|
||||
{L("Add support blocker"), "support_blocker"}, // ~ModelVolumeType::SUPPORT_BLOCKER
|
||||
{L("Add support enforcer"), "support_enforcer"}, // ~ModelVolumeType::SUPPORT_ENFORCER
|
||||
};
|
||||
static const constexpr std::array<std::pair<const char *, const char *>, 5> ADD_VOLUME_MENU_ITEMS = {{
|
||||
// menu_item Name menu_item bitmap name
|
||||
{L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART
|
||||
{L("Add negative volume"), "add_negative" }, // ~ModelVolumeType::NEGATIVE_VOLUME
|
||||
{L("Add modifier"), "add_modifier"}, // ~ModelVolumeType::PARAMETER_MODIFIER
|
||||
{L("Add support blocker"), "support_blocker"}, // ~ModelVolumeType::SUPPORT_BLOCKER
|
||||
{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
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
// don't add settings menu items
|
||||
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
|
||||
return nullptr;
|
||||
|
||||
@ -1066,6 +1114,8 @@ void MenuFactory::create_sla_object_menu()
|
||||
[]() { return plater()->can_split(true); }, m_parent);
|
||||
|
||||
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)
|
||||
|
@ -92,6 +92,7 @@ private:
|
||||
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_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_settings(wxMenu* menu);
|
||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
|
||||
|
@ -53,8 +53,8 @@ void GLGizmoHollow::data_changed()
|
||||
reload_cache();
|
||||
m_old_mo_id = mo->id();
|
||||
}
|
||||
if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh())
|
||||
m_holes_in_drilled_mesh = mo->sla_drain_holes;
|
||||
// if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh())
|
||||
// m_holes_in_drilled_mesh = mo->sla_drain_holes;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (m_raycasters.empty())
|
||||
on_register_raycasters_for_picking();
|
||||
@ -206,11 +206,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
#endif // !ENABLE_RAYCAST_PICKING
|
||||
if (size_t(m_hover_id) == i)
|
||||
render_color = ColorRGBA::CYAN();
|
||||
else if (m_c->hollowed_mesh() &&
|
||||
i < m_c->hollowed_mesh()->get_drainholes().size() &&
|
||||
m_c->hollowed_mesh()->get_drainholes()[i].failed) {
|
||||
render_color = { 1.0f, 0.0f, 0.0f, 0.5f };
|
||||
}
|
||||
// else if (m_c->hollowed_mesh() &&
|
||||
// i < m_c->hollowed_mesh()->get_drainholes().size() &&
|
||||
// m_c->hollowed_mesh()->get_drainholes()[i].failed) {
|
||||
// render_color = { 1.0f, 0.0f, 0.0f, 0.5f };
|
||||
// }
|
||||
else
|
||||
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
|
||||
@ -314,18 +314,18 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, V
|
||||
normal,
|
||||
clp_dist != 0. ? clp : nullptr))
|
||||
{
|
||||
if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_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
|
||||
// to ignore it.
|
||||
for (const sla::DrainHole& hole : m_holes_in_drilled_mesh) {
|
||||
sla::DrainHole outer(hole);
|
||||
outer.radius *= 1.001f;
|
||||
outer.height *= 1.001f;
|
||||
if (outer.is_inside(hit))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_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
|
||||
// // to ignore it.
|
||||
// for (const sla::DrainHole& hole : m_holes_in_drilled_mesh) {
|
||||
// sla::DrainHole outer(hole);
|
||||
// outer.radius *= 1.001f;
|
||||
// outer.height *= 1.001f;
|
||||
// if (outer.is_inside(hit))
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Return both the point and the facet normal.
|
||||
pos_and_normal = std::make_pair(hit, normal);
|
||||
|
@ -86,6 +86,8 @@ void GLGizmoSlaSupports::data_changed()
|
||||
update_raycasters_for_picking_transform();
|
||||
#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 bool has_points = (cache_size != 0);
|
||||
const bool has_holes = (! m_c->hollowed_mesh()->get_hollowed_mesh()
|
||||
&& ! m_c->selection_info()->model_object()->sla_drain_holes.empty());
|
||||
const bool has_holes = (/*! m_c->hollowed_mesh()->get_hollowed_mesh()
|
||||
&&*/ ! m_c->selection_info()->model_object()->sla_drain_holes.empty());
|
||||
|
||||
if (! has_points && ! has_holes)
|
||||
return;
|
||||
@ -304,7 +306,8 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
if (m_editing_mode) {
|
||||
// in case the normal is not yet cached, find and cache it
|
||||
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;
|
||||
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.
|
||||
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;
|
||||
|
||||
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
|
||||
Vec3f hit;
|
||||
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,
|
||||
trafo.get_matrix(),
|
||||
camera,
|
||||
@ -477,24 +480,24 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec
|
||||
clp_dist != 0. ? clp : nullptr))
|
||||
{
|
||||
// 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
|
||||
// placing points in holes, because they should never end up
|
||||
// on surface that's been drilled away.
|
||||
if (! m_c->hollowed_mesh()->get_hollowed_mesh()) {
|
||||
sla::DrainHoles drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
|
||||
for (const sla::DrainHole& hole : drain_holes) {
|
||||
if (hole.is_inside(hit)) {
|
||||
in_hole = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! in_hole) {
|
||||
// if (! m_c->hollowed_mesh()->get_hollowed_mesh()) {
|
||||
// sla::DrainHoles drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
|
||||
// for (const sla::DrainHole& hole : drain_holes) {
|
||||
// if (hole.is_inside(hit)) {
|
||||
// in_hole = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (! in_hole) {
|
||||
// Return both the point and the facet normal.
|
||||
pos_and_normal = std::make_pair(hit, normal);
|
||||
return true;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -589,7 +592,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
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>());
|
||||
|
||||
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,
|
||||
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;
|
||||
|
||||
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;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
|
||||
|
@ -25,7 +25,7 @@ private:
|
||||
|
||||
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 {
|
||||
public:
|
||||
|
@ -23,7 +23,7 @@ CommonGizmosDataPool::CommonGizmosDataPool(GLCanvas3D* canvas)
|
||||
using c = CommonGizmosDataID;
|
||||
m_data[c::SelectionInfo].reset( new SelectionInfo(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::ObjectClipper].reset( new ObjectClipper(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;
|
||||
}
|
||||
|
||||
HollowedMesh* CommonGizmosDataPool::hollowed_mesh() const
|
||||
{
|
||||
HollowedMesh* hol_mesh = dynamic_cast<HollowedMesh*>(m_data.at(CommonGizmosDataID::HollowedMesh).get());
|
||||
assert(hol_mesh);
|
||||
return hol_mesh->is_valid() ? hol_mesh : nullptr;
|
||||
}
|
||||
//HollowedMesh* CommonGizmosDataPool::hollowed_mesh() const
|
||||
//{
|
||||
// HollowedMesh* hol_mesh = dynamic_cast<HollowedMesh*>(m_data.at(CommonGizmosDataID::HollowedMesh).get());
|
||||
// assert(hol_mesh);
|
||||
// return hol_mesh->is_valid() ? hol_mesh : nullptr;
|
||||
//}
|
||||
|
||||
Raycaster* CommonGizmosDataPool::raycaster() const
|
||||
{
|
||||
@ -117,16 +117,18 @@ bool CommonGizmosDataPool::check_dependencies(CommonGizmosDataID required) const
|
||||
void SelectionInfo::on_update()
|
||||
{
|
||||
const Selection& selection = get_pool()->get_canvas()->get_selection();
|
||||
|
||||
m_model_object = nullptr;
|
||||
m_print_object = nullptr;
|
||||
|
||||
if (selection.is_single_full_instance()) {
|
||||
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();
|
||||
}
|
||||
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()
|
||||
@ -253,78 +255,78 @@ void InstancesHider::render_cut() const
|
||||
|
||||
|
||||
|
||||
void HollowedMesh::on_update()
|
||||
{
|
||||
const ModelObject* mo = get_pool()->selection_info()->model_object();
|
||||
bool is_sla = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA;
|
||||
if (! mo || ! is_sla)
|
||||
return;
|
||||
//void HollowedMesh::on_update()
|
||||
//{
|
||||
// const ModelObject* mo = get_pool()->selection_info()->model_object();
|
||||
// bool is_sla = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA;
|
||||
// if (! mo || ! is_sla)
|
||||
// return;
|
||||
|
||||
const GLCanvas3D* canvas = get_pool()->get_canvas();
|
||||
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()))
|
||||
? print_objects[m_print_object_idx]
|
||||
: nullptr;
|
||||
// const GLCanvas3D* canvas = get_pool()->get_canvas();
|
||||
// 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()))
|
||||
// ? print_objects[m_print_object_idx]
|
||||
// : nullptr;
|
||||
|
||||
// Find the respective SLAPrintObject.
|
||||
if (m_print_object_idx < 0 || m_print_objects_count != int(print_objects.size())) {
|
||||
m_print_objects_count = print_objects.size();
|
||||
m_print_object_idx = -1;
|
||||
for (const SLAPrintObject* po : print_objects) {
|
||||
++m_print_object_idx;
|
||||
if (po->model_object()->id() == mo->id()) {
|
||||
print_object = po;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// // Find the respective SLAPrintObject.
|
||||
// if (m_print_object_idx < 0 || m_print_objects_count != int(print_objects.size())) {
|
||||
// m_print_objects_count = print_objects.size();
|
||||
// m_print_object_idx = -1;
|
||||
// for (const SLAPrintObject* po : print_objects) {
|
||||
// ++m_print_object_idx;
|
||||
// if (po->model_object()->id() == mo->id()) {
|
||||
// print_object = po;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// If there is a valid SLAPrintObject, check state of Hollowing step.
|
||||
if (print_object) {
|
||||
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;
|
||||
if (timestamp > m_old_hollowing_timestamp) {
|
||||
const TriangleMesh& backend_mesh = print_object->get_mesh_to_print();
|
||||
if (! backend_mesh.empty()) {
|
||||
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();
|
||||
m_hollowed_mesh_transformed->transform(trafo_inv);
|
||||
m_drainholes = print_object->model_object()->sla_drain_holes;
|
||||
m_old_hollowing_timestamp = timestamp;
|
||||
// // If there is a valid SLAPrintObject, check state of Hollowing step.
|
||||
// if (print_object) {
|
||||
// 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;
|
||||
// if (timestamp > m_old_hollowing_timestamp) {
|
||||
// const TriangleMesh& backend_mesh = print_object->get_mesh_to_print();
|
||||
// if (! backend_mesh.empty()) {
|
||||
// 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();
|
||||
// m_hollowed_mesh_transformed->transform(trafo_inv);
|
||||
// m_drainholes = print_object->model_object()->sla_drain_holes;
|
||||
// m_old_hollowing_timestamp = timestamp;
|
||||
|
||||
// indexed_triangle_set interior = print_object->hollowed_interior_mesh();
|
||||
// its_flip_triangles(interior);
|
||||
// m_hollowed_interior_transformed = std::make_unique<TriangleMesh>(std::move(interior));
|
||||
// m_hollowed_interior_transformed->transform(trafo_inv);
|
||||
}
|
||||
else {
|
||||
m_hollowed_mesh_transformed.reset(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_hollowed_mesh_transformed.reset(nullptr);
|
||||
}
|
||||
}
|
||||
//// indexed_triangle_set interior = print_object->hollowed_interior_mesh();
|
||||
//// its_flip_triangles(interior);
|
||||
//// m_hollowed_interior_transformed = std::make_unique<TriangleMesh>(std::move(interior));
|
||||
//// m_hollowed_interior_transformed->transform(trafo_inv);
|
||||
// }
|
||||
// else {
|
||||
// m_hollowed_mesh_transformed.reset(nullptr);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// m_hollowed_mesh_transformed.reset(nullptr);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
void HollowedMesh::on_release()
|
||||
{
|
||||
m_hollowed_mesh_transformed.reset();
|
||||
m_old_hollowing_timestamp = 0;
|
||||
m_print_object_idx = -1;
|
||||
}
|
||||
//void HollowedMesh::on_release()
|
||||
//{
|
||||
// m_hollowed_mesh_transformed.reset();
|
||||
// m_old_hollowing_timestamp = 0;
|
||||
// m_print_object_idx = -1;
|
||||
//}
|
||||
|
||||
|
||||
const TriangleMesh* HollowedMesh::get_hollowed_mesh() const
|
||||
{
|
||||
return m_hollowed_mesh_transformed.get();
|
||||
}
|
||||
//const TriangleMesh* HollowedMesh::get_hollowed_mesh() const
|
||||
//{
|
||||
// return m_hollowed_mesh_transformed.get();
|
||||
//}
|
||||
|
||||
const TriangleMesh* HollowedMesh::get_hollowed_interior() const
|
||||
{
|
||||
return m_hollowed_interior_transformed.get();
|
||||
}
|
||||
//const TriangleMesh* HollowedMesh::get_hollowed_interior() const
|
||||
//{
|
||||
// return m_hollowed_interior_transformed.get();
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@ -345,12 +347,13 @@ void Raycaster::on_update()
|
||||
mvs = mo->volumes;
|
||||
|
||||
std::vector<const TriangleMesh*> meshes;
|
||||
if (mvs.size() == 1) {
|
||||
assert(mvs.front()->is_model_part());
|
||||
const HollowedMesh* hollowed_mesh_tracker = get_pool()->hollowed_mesh();
|
||||
if (hollowed_mesh_tracker && hollowed_mesh_tracker->get_hollowed_mesh())
|
||||
meshes.push_back(hollowed_mesh_tracker->get_hollowed_mesh());
|
||||
}
|
||||
const std::vector<ModelVolume*>& mvs = mo->volumes;
|
||||
// if (mvs.size() == 1) {
|
||||
// assert(mvs.front()->is_model_part());
|
||||
// const HollowedMesh* hollowed_mesh_tracker = get_pool()->hollowed_mesh();
|
||||
// if (hollowed_mesh_tracker && hollowed_mesh_tracker->get_hollowed_mesh())
|
||||
// meshes.push_back(hollowed_mesh_tracker->get_hollowed_mesh());
|
||||
// }
|
||||
if (meshes.empty()) {
|
||||
for (const ModelVolume* v : mvs) {
|
||||
if (v->is_model_part())
|
||||
@ -396,9 +399,9 @@ void ObjectClipper::on_update()
|
||||
|
||||
// which mesh should be cut?
|
||||
std::vector<const TriangleMesh*> meshes;
|
||||
bool has_hollowed = get_pool()->hollowed_mesh() && get_pool()->hollowed_mesh()->get_hollowed_mesh();
|
||||
if (has_hollowed)
|
||||
meshes.push_back(get_pool()->hollowed_mesh()->get_hollowed_mesh());
|
||||
// bool has_hollowed = get_pool()->hollowed_mesh() && get_pool()->hollowed_mesh()->get_hollowed_mesh();
|
||||
// if (has_hollowed)
|
||||
// meshes.push_back(get_pool()->hollowed_mesh()->get_hollowed_mesh());
|
||||
|
||||
if (meshes.empty())
|
||||
for (const ModelVolume* mv : mo->volumes)
|
||||
@ -412,8 +415,8 @@ void ObjectClipper::on_update()
|
||||
}
|
||||
m_old_meshes = meshes;
|
||||
|
||||
if (has_hollowed)
|
||||
m_clippers.front()->set_negative_mesh(*get_pool()->hollowed_mesh()->get_hollowed_interior());
|
||||
// if (has_hollowed)
|
||||
// m_clippers.front()->set_negative_mesh(*get_pool()->hollowed_mesh()->get_hollowed_interior());
|
||||
|
||||
m_active_inst_bb_radius =
|
||||
mo->instance_bounding_box(get_pool()->selection_info()->get_active_instance()).radius();
|
||||
|
@ -5,11 +5,11 @@
|
||||
#include <map>
|
||||
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
#include "libslic3r/SLA/Hollowing.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ModelObject;
|
||||
class SLAPrintObject;
|
||||
class ModelVolume;
|
||||
|
||||
namespace GUI {
|
||||
@ -85,7 +85,7 @@ public:
|
||||
// Getters for the data that need to be accessed from the gizmos directly.
|
||||
CommonGizmosDataObjects::SelectionInfo* selection_info() const;
|
||||
CommonGizmosDataObjects::InstancesHider* instances_hider() const;
|
||||
CommonGizmosDataObjects::HollowedMesh* hollowed_mesh() const;
|
||||
// CommonGizmosDataObjects::HollowedMesh* hollowed_mesh() const;
|
||||
CommonGizmosDataObjects::Raycaster* raycaster() const;
|
||||
CommonGizmosDataObjects::ObjectClipper* object_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
|
||||
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
|
||||
ModelVolume* model_volume() const { return m_model_volume; }
|
||||
int get_active_instance() const;
|
||||
@ -169,6 +170,7 @@ protected:
|
||||
|
||||
private:
|
||||
ModelObject* m_model_object = nullptr;
|
||||
const SLAPrintObject *m_print_object = nullptr;
|
||||
ModelVolume* m_model_volume = nullptr;
|
||||
// int m_active_inst = -1;
|
||||
float m_z_shift = 0.f;
|
||||
@ -201,32 +203,32 @@ private:
|
||||
|
||||
|
||||
|
||||
class HollowedMesh : public CommonGizmosDataBase
|
||||
{
|
||||
public:
|
||||
explicit HollowedMesh(CommonGizmosDataPool* cgdp)
|
||||
: CommonGizmosDataBase(cgdp) {}
|
||||
#ifndef NDEBUG
|
||||
CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; }
|
||||
#endif // NDEBUG
|
||||
//class HollowedMesh : public CommonGizmosDataBase
|
||||
//{
|
||||
//public:
|
||||
// explicit HollowedMesh(CommonGizmosDataPool* cgdp)
|
||||
// : CommonGizmosDataBase(cgdp) {}
|
||||
//#ifndef NDEBUG
|
||||
// CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; }
|
||||
//#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_interior() const;
|
||||
// const TriangleMesh* get_hollowed_mesh() const;
|
||||
// const TriangleMesh* get_hollowed_interior() const;
|
||||
|
||||
protected:
|
||||
void on_update() override;
|
||||
void on_release() override;
|
||||
//protected:
|
||||
// void on_update() override;
|
||||
// void on_release() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<TriangleMesh> m_hollowed_mesh_transformed;
|
||||
std::unique_ptr<TriangleMesh> m_hollowed_interior_transformed;
|
||||
size_t m_old_hollowing_timestamp = 0;
|
||||
int m_print_object_idx = -1;
|
||||
int m_print_objects_count = 0;
|
||||
sla::DrainHoles m_drainholes;
|
||||
};
|
||||
//private:
|
||||
// std::unique_ptr<TriangleMesh> m_hollowed_mesh_transformed;
|
||||
// std::unique_ptr<TriangleMesh> m_hollowed_interior_transformed;
|
||||
// size_t m_old_hollowing_timestamp = 0;
|
||||
// int m_print_object_idx = -1;
|
||||
// int m_print_objects_count = 0;
|
||||
// sla::DrainHoles m_drainholes;
|
||||
//};
|
||||
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// 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 ((type_3mf && !is_project_file) || (type_any_amf && !type_zip_amf))
|
||||
model.center_instances_around_point(this->bed.build_volume().bed_center());
|
||||
|
@ -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();
|
||||
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) {
|
||||
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>();
|
||||
HitResult current_hit = { type };
|
||||
for (std::shared_ptr<SceneRaycasterItem> item : *raycasters) {
|
||||
@ -214,6 +214,20 @@ std::vector<std::shared_ptr<SceneRaycasterItem>>* SceneRaycaster::get_raycasters
|
||||
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)
|
||||
{
|
||||
switch (type)
|
||||
|
@ -89,10 +89,11 @@ public:
|
||||
void remove_raycaster(std::shared_ptr<SceneRaycasterItem> item);
|
||||
|
||||
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; }
|
||||
|
||||
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
|
||||
void render_hit(const Camera& camera);
|
||||
|
@ -62,18 +62,18 @@ Selection::VolumeCache::VolumeCache(const Geometry::Transformation& volume_trans
|
||||
|
||||
bool Selection::Clipboard::is_sla_compliant() const
|
||||
{
|
||||
if (m_mode == Selection::Volume)
|
||||
return false;
|
||||
// if (m_mode == Selection::Volume)
|
||||
// return false;
|
||||
|
||||
for (const ModelObject* o : m_model->objects) {
|
||||
if (o->is_multiparts())
|
||||
return false;
|
||||
// for (const ModelObject* o : m_model->objects) {
|
||||
// if (o->is_multiparts())
|
||||
// return false;
|
||||
|
||||
for (const ModelVolume* v : o->volumes) {
|
||||
if (v->is_modifier())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// for (const ModelVolume* v : o->volumes) {
|
||||
// if (v->is_modifier())
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -571,13 +571,13 @@ bool Selection::is_from_single_object() const
|
||||
|
||||
bool Selection::is_sla_compliant() const
|
||||
{
|
||||
if (m_mode == Volume)
|
||||
return false;
|
||||
// if (m_mode == Volume)
|
||||
// return false;
|
||||
|
||||
for (unsigned int i : m_list) {
|
||||
if ((*m_volumes)[i]->is_modifier)
|
||||
return false;
|
||||
}
|
||||
// for (unsigned int i : m_list) {
|
||||
// if ((*m_volumes)[i]->is_modifier)
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -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);
|
||||
PrinterTechnology old_printer_technology = m_presets->get_edited_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;
|
||||
else {
|
||||
else */{
|
||||
struct PresetUpdate {
|
||||
Preset::Type tab_type;
|
||||
PresetCollection *presets;
|
||||
|
Loading…
x
Reference in New Issue
Block a user