From e8cfe35f78a99bd9b3641bd0af0afe8b84969462 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Tue, 8 Mar 2022 19:15:56 +0100 Subject: [PATCH] Do not use RaycastManager inside job Separate Jobs for Creation of volume from creation of Object --- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 82 +++++-- src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp | 2 + src/slic3r/GUI/Jobs/EmbossJob.cpp | 305 ++++++++++++++---------- src/slic3r/GUI/Jobs/EmbossJob.hpp | 131 ++++++---- src/slic3r/Utils/RaycastManager.cpp | 43 ++-- src/slic3r/Utils/RaycastManager.hpp | 12 +- 6 files changed, 354 insertions(+), 221 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 424f897f50..36a38accd4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -145,30 +145,18 @@ void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mous screen_coor.y() = screen_size.get_height() / 2.; } - std::optional object_idx; + if (start_volume_creation(volume_type, screen_coor)) return; - std::optional hit_vol_tr; - const Selection &selection = m_parent.get_selection(); - if (!selection.is_empty()) { - object_idx = selection.get_object_idx(); - int hovered_id = m_parent.get_first_hover_volume_idx(); - if (hovered_id >= 0) { - GLVolume *gl_volume = m_parent.get_volumes().volumes[hovered_id]; - hit_vol_tr = gl_volume->get_instance_transformation().get_matrix(); - } - } + // start creation of new object Plater* plater = wxGetApp().plater(); const Camera &camera = plater->get_camera(); - auto data = std::make_unique( - m_font_manager.get_font().font_file_with_cache, - create_configuration(), - create_volume_name(), volume_type, screen_coor, object_idx, - hit_vol_tr, camera, - plater->build_volume().bed_shape(), - &m_raycast_manager); - - auto &worker = plater->get_ui_job_worker(); - queue_job(worker, std::make_unique(std::move(data))); + const Pointfs &bed_shape = plater->build_volume().bed_shape(); + auto &worker = plater->get_ui_job_worker(); + auto data = std::make_unique( + m_font_manager.get_font().font_file_with_cache, + create_configuration(), create_volume_name(), + screen_coor, camera, bed_shape); + queue_job(worker, std::make_unique(std::move(data))); } #ifdef DRAW_PLACE_TO_ADD_TEXT @@ -599,6 +587,58 @@ void GLGizmoEmboss::set_default_text() m_text = _u8L("Embossed text"); } +bool GLGizmoEmboss::start_volume_creation(ModelVolumeType volume_type, + const Vec2d &screen_coor) +{ + Plater* plater = wxGetApp().plater(); + + const Selection &selection = m_parent.get_selection(); + if (selection.is_empty()) return false; + + int hovered_id_signed = m_parent.get_first_hover_volume_idx(); + if (hovered_id_signed < 0) return false; + + size_t hovered_id = static_cast(hovered_id_signed); + auto &volumes = m_parent.get_volumes().volumes; + if (hovered_id >= volumes.size()) return false; + + int object_idx_signed = selection.get_object_idx(); + if (object_idx_signed < 0) return false; + + size_t object_idx = static_cast(object_idx_signed); + auto &objects = plater->model().objects; + if (object_idx >= objects.size()) return false; + + ModelObject *obj = objects[object_idx]; + m_raycast_manager.actualize(obj); + + const Camera &camera = plater->get_camera(); + std::optional hit = + m_raycast_manager.unproject(screen_coor, camera); + + // context menu for add text could be open only by right click on an + // object. After right click, object is selected and object_idx is set + // also hit must exist. But there is proper behavior when hit doesn't + // exists. When this assert appear distquish remove of it. + assert(hit.has_value()); + if (!hit.has_value()) return false; + + Transform3d hit_object_trmat = m_raycast_manager.get_transformation(hit->tr_key); + + GLVolume *gl_volume = volumes[hovered_id]; + Transform3d hit_instance_trmat = gl_volume->get_instance_transformation().get_matrix(); + + // create volume + auto &worker = plater->get_ui_job_worker(); + auto data = std::make_unique( + m_font_manager.get_font().font_file_with_cache, + create_configuration(), create_volume_name(), volume_type, + screen_coor, object_idx, camera, *hit, hit_object_trmat, + hit_instance_trmat); + queue_job(worker, std::make_unique(std::move(data))); + return true; +} + #include "imgui/imgui_internal.h" // to unfocus input --> ClearActiveID void GLGizmoEmboss::check_selection() { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp index ada7a25378..6801ee112a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp @@ -81,6 +81,8 @@ private: static FontList create_default_font_list(); void set_default_text(); + bool start_volume_creation(ModelVolumeType volume_type, const Vec2d &screen_coor); + void check_selection(); // more general function --> move to select ModelVolume *get_selected_volume(); diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp index 7e8c50645a..b05ca2e4fc 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.cpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp @@ -19,14 +19,43 @@ using namespace Slic3r; using namespace GUI; +// private namespace +namespace priv{ +// +/// Create mesh from text +/// +/// Text to convert on mesh +/// Define shape of characters. +/// NOTE: Can't be const cache glyphs +/// Property of font +/// Control for job, check of cancelation +/// Triangle mesh model +static TriangleMesh create_mesh(const char *text, + Emboss::FontFileWithCache &font, + const FontProp &font_prop, + GUI::Job::Ctl &ctl); +/// +/// Create default mesh for embossed text +/// +/// Not empty model(index trinagle set - its) +static TriangleMesh create_default_mesh(); +} + + +///////////////// +/// Update Volume +EmbossUpdateJob::EmbossUpdateJob(std::unique_ptr input) + : m_input(std::move(input)) +{} + void EmbossUpdateJob::process(Ctl &ctl) { // check if exist valid font if (!m_input->font_file.has_value()) return; const TextConfiguration &cfg = m_input->text_configuration; - m_result = EmbossCreateJob::create_mesh( - cfg.text.c_str(), m_input->font_file, cfg.font_item.prop, ctl); + m_result = priv::create_mesh(cfg.text.c_str(), m_input->font_file, + cfg.font_item.prop, ctl); if (m_result.its.empty()) return; if (ctl.was_canceled()) return; @@ -95,155 +124,169 @@ void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &) canvas->reload_scene(true); } -void EmbossCreateJob::process(Ctl &ctl) { + +///////////////// +/// Create Volume +EmbossCreateVolumeJob::EmbossCreateVolumeJob( + std::unique_ptr input) + : m_input(std::move(input)) +{} + +void EmbossCreateVolumeJob::process(Ctl &ctl) { // It is neccessary to create some shape // Emboss text window is opened by creation new emboss text object const char *text = m_input->text_configuration.text.c_str(); FontProp &prop = m_input->text_configuration.font_item.prop; - m_result = (m_input->font_file.has_value()) ? - create_mesh(text, m_input->font_file, prop, ctl): - create_default_mesh(); - if (m_result.its.empty()) m_result = create_default_mesh(); + + m_result = priv::create_mesh(text, m_input->font_file, prop, ctl); + if (m_result.its.empty()) m_result = priv::create_default_mesh(); + if (ctl.was_canceled()) return; - - std::optional hit; - if (m_input->object_idx.has_value()) { - // By position of cursor create transformation to put text on surface of model - ModelObject *obj = wxGetApp().plater()->model().objects[*m_input->object_idx]; - m_input->raycast_manager->actualize(obj); - if (ctl.was_canceled()) return; - hit = m_input->raycast_manager->unproject(m_input->screen_coor, m_input->camera); - - // context menu for add text could be open only by right click on an - // object. After right click, object is selected and object_idx is set - // also hit must exist. But there is proper behavior when hit doesn't - // exists. When this assert appear distquish remove of it. - assert(hit.has_value()); - if (!hit.has_value()) m_input->object_idx.reset(); - } - if (!hit.has_value()) { - // create new object - // calculate X,Y offset position for lay on platter in place of - // mouse click - Vec2d bed_coor = CameraUtils::get_z0_position(m_input->camera, m_input->screen_coor); - - // check point is on build plate: - Points bed_shape_; - bed_shape_.reserve(m_input->bed_shape.size()); - for (const Vec2d &p : m_input->bed_shape) - bed_shape_.emplace_back(p.cast()); - Polygon bed(bed_shape_); - if (!bed.contains(bed_coor.cast())) - // mouse pose is out of build plate so create object in center of plate - bed_coor = bed.centroid().cast(); - - double z = m_input->text_configuration.font_item.prop.emboss / 2; - Vec3d offset(bed_coor.x(), bed_coor.y(), z); - offset -= m_result.center(); - Transform3d::TranslationType tt(offset.x(), offset.y(), offset.z()); - m_transformation = Transform3d(tt); - } else { - //m_transformation = Emboss::create_transformation_onto_surface(hit->position, hit->normal); - assert(m_input->hit_vol_tr.has_value()); - if (m_input->hit_vol_tr.has_value()) { - Transform3d object_trmat = m_input->raycast_manager->get_transformation(hit->tr_key); - const FontProp &font_prop = m_input->text_configuration.font_item.prop; - Transform3d surface_trmat = Emboss::create_transformation_onto_surface(hit->position, hit->normal); - Emboss::apply_transformation(font_prop, surface_trmat); - m_transformation = m_input->hit_vol_tr->inverse() * object_trmat * surface_trmat; - } - } + + // Create new volume inside of object + const FontProp &font_prop = m_input->text_configuration.font_item.prop; + Transform3d surface_trmat = Emboss::create_transformation_onto_surface( + m_input->hit.position, m_input->hit.normal); + Emboss::apply_transformation(font_prop, surface_trmat); + m_transformation = m_input->hit_instance_tr.inverse() * + m_input->hit_object_tr * surface_trmat; } -void EmbossCreateJob::finalize(bool canceled, std::exception_ptr &) -{ +void EmbossCreateVolumeJob::finalize(bool canceled, std::exception_ptr &) { if (canceled) return; - - GUI_App & app = wxGetApp(); - Plater * plater = app.plater(); + + GUI_App &app = wxGetApp(); + Plater *plater = app.plater(); ObjectList *obj_list = app.obj_list(); GLCanvas3D *canvas = plater->canvas3D(); + Model &model = plater->model(); - // decide if create object or volume - bool create_object = !m_input->object_idx.has_value(); - if (create_object) { - Plater::TakeSnapshot snapshot(plater, _L("Add Emboss text object")); - // Create new object and change selection - bool center = false; - obj_list->load_mesh_object(std::move(m_result), m_input->volume_name, center, - &m_input->text_configuration, &m_transformation); + // create volume in object + size_t object_idx = m_input->object_idx; + assert(model.objects.size() > object_idx); + if (model.objects.size() <= object_idx) return; - // When add new object selection is empty. - // When cursor move and no one object is selected than Manager::reset_all() - // So Gizmo could be closed on end of creation object - GLGizmosManager &manager = canvas->get_gizmos_manager(); - if (manager.get_current_type() != GLGizmosManager::Emboss) - manager.open_gizmo(GLGizmosManager::Emboss); - } else { - // create volume in object - size_t object_idx = *m_input->object_idx; - ModelVolumeType type = m_input->volume_type; + Plater::TakeSnapshot snapshot(plater, _L("Add Emboss text Volume")); - // create new volume inside of object - Model &model = plater->model(); - if (model.objects.size() <= object_idx) return; - ModelObject *obj = model.objects[object_idx]; - ModelVolume *volume = obj->add_volume(std::move(m_result)); + ModelObject *obj = model.objects[object_idx]; + ModelVolumeType type = m_input->volume_type; + ModelVolume *volume = obj->add_volume(std::move(m_result), type); - // set a default extruder value, since user can't add it manually - volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + // set a default extruder value, since user can't add it manually + volume->config.set_key_value("extruder", new ConfigOptionInt(0)); - // do not allow model reload from disk - volume->source.is_from_builtin_objects = true; - volume->set_type(type); - volume->name = m_input->volume_name; - volume->text_configuration = m_input->text_configuration; - volume->set_transformation(m_transformation); + // do not allow model reload from disk + volume->source.is_from_builtin_objects = true; - // update volume name in object list - // updata selection after new volume added - // change name of volume in right panel - // select only actual volume - // when new volume is created change selection to this volume - auto add_to_selection = [volume](const ModelVolume *vol) { - return vol == volume; - }; - wxDataViewItemArray sel = - obj_list->reorder_volumes_and_get_selection((int) object_idx, - add_to_selection); - if (!sel.IsEmpty()) obj_list->select_item(sel.front()); + volume->name = m_input->volume_name; + volume->text_configuration = std::move(m_input->text_configuration); + volume->set_transformation(m_transformation); - // update printable state on canvas - if (type == ModelVolumeType::MODEL_PART) - canvas->update_instance_printable_state_for_object(object_idx); + // update volume name in object list + // updata selection after new volume added + // change name of volume in right panel + // select only actual volume + // when new volume is created change selection to this volume + auto add_to_selection = [volume](const ModelVolume *vol) { + return vol == volume; + }; + wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection( + (int) object_idx, add_to_selection); + if (!sel.IsEmpty()) obj_list->select_item(sel.front()); - obj_list->selection_changed(); + // update printable state on canvas + if (type == ModelVolumeType::MODEL_PART) + canvas->update_instance_printable_state_for_object(object_idx); + + obj_list->selection_changed(); + + // WHY selection_changed set manipulation to world ??? + // so I set it back to local --> RotationGizmo need it + ObjectManipulation *manipul = wxGetApp().obj_manipul(); + manipul->set_coordinates_type(ECoordinatesType::Local); - // WHY selection_changed set manipulation to world ??? - // so I set it back to local --> RotationGizmo need it - ObjectManipulation *manipul = wxGetApp().obj_manipul(); - manipul->set_coordinates_type(ECoordinatesType::Local); - } // redraw scene canvas->reload_scene(true); } -TriangleMesh EmbossCreateJob::create_default_mesh() + +///////////////// +/// Create Object +EmbossCreateObjectJob::EmbossCreateObjectJob( + std::unique_ptr input) + : m_input(std::move(input)) +{} + +void EmbossCreateObjectJob::process(Ctl &ctl) { - // When cant load any font use default object loaded from file - std::string path = Slic3r::resources_dir() + "/data/embossed_text.stl"; - TriangleMesh triangle_mesh; - if (!load_obj(path.c_str(), &triangle_mesh)) { - // when can't load mesh use cube - return TriangleMesh(its_make_cube(36., 4., 2.5)); - } - return triangle_mesh; + // It is neccessary to create some shape + // Emboss text window is opened by creation new emboss text object + const char *text = m_input->text_configuration.text.c_str(); + FontProp &prop = m_input->text_configuration.font_item.prop; + + m_result = priv::create_mesh(text, m_input->font_file, prop, ctl); + if (m_result.its.empty()) m_result = priv::create_default_mesh(); + + if (ctl.was_canceled()) return; + + // Create new object + // calculate X,Y offset position for lay on platter in place of + // mouse click + Vec2d bed_coor = CameraUtils::get_z0_position( + m_input->camera, m_input->screen_coor); + + // check point is on build plate: + Points bed_shape_; + bed_shape_.reserve(m_input->bed_shape.size()); + for (const Vec2d &p : m_input->bed_shape) + bed_shape_.emplace_back(p.cast()); + Polygon bed(bed_shape_); + if (!bed.contains(bed_coor.cast())) + // mouse pose is out of build plate so create object in center of plate + bed_coor = bed.centroid().cast(); + + double z = m_input->text_configuration.font_item.prop.emboss / 2; + Vec3d offset(bed_coor.x(), bed_coor.y(), z); + offset -= m_result.center(); + Transform3d::TranslationType tt(offset.x(), offset.y(), offset.z()); + m_transformation = Transform3d(tt); } -TriangleMesh EmbossCreateJob::create_mesh(const char *text, - Emboss::FontFileWithCache &font, - const FontProp &font_prop, - Ctl &ctl) +void EmbossCreateObjectJob::finalize(bool canceled, std::exception_ptr &) +{ + if (canceled) return; + + GUI_App &app = wxGetApp(); + Plater *plater = app.plater(); + ObjectList *obj_list = app.obj_list(); + GLCanvas3D *canvas = plater->canvas3D(); + + Plater::TakeSnapshot snapshot(plater, _L("Add Emboss text object")); + + // Create new object and change selection + bool center = false; + obj_list->load_mesh_object(std::move(m_result), m_input->volume_name, + center, &m_input->text_configuration, + &m_transformation); + + // When add new object selection is empty. + // When cursor move and no one object is selected than + // Manager::reset_all() So Gizmo could be closed before end of creation object + GLGizmosManager &manager = canvas->get_gizmos_manager(); + if (manager.get_current_type() != GLGizmosManager::Emboss) + manager.open_gizmo(GLGizmosManager::Emboss); + + // redraw scene + canvas->reload_scene(true); +} + + +//////////////////////////// +/// private namespace implementation +TriangleMesh priv::create_mesh(const char *text, + Emboss::FontFileWithCache &font, + const FontProp &font_prop, + GUI::Job::Ctl &ctl) { assert(font.has_value()); if (!font.has_value()) return {}; @@ -259,4 +302,16 @@ TriangleMesh EmbossCreateJob::create_mesh(const char *text, Emboss::ProjectScale project(std::move(projectZ), scale); if (ctl.was_canceled()) return {}; return TriangleMesh(Emboss::polygons2model(shapes, project)); +} + +TriangleMesh priv::create_default_mesh() +{ + // When cant load any font use default object loaded from file + std::string path = Slic3r::resources_dir() + "/data/embossed_text.stl"; + TriangleMesh triangle_mesh; + if (!load_obj(path.c_str(), &triangle_mesh)) { + // when can't load mesh use cube + return TriangleMesh(its_make_cube(36., 4., 2.5)); + } + return triangle_mesh; } \ No newline at end of file diff --git a/src/slic3r/GUI/Jobs/EmbossJob.hpp b/src/slic3r/GUI/Jobs/EmbossJob.hpp index 67fc7823a7..1d9543dd90 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.hpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.hpp @@ -15,46 +15,53 @@ class TriangleMesh; namespace Slic3r::GUI { struct EmbossDataUpdate; -struct EmbossDataCreate; +struct EmbossDataCreateVolume; +struct EmbossDataCreateObject; +/// +/// Update text shape in existing text volume +/// class EmbossUpdateJob : public Job { std::unique_ptr m_input; - TriangleMesh m_result; + TriangleMesh m_result; + public: - EmbossUpdateJob(std::unique_ptr input) : m_input(std::move(input)) {} + EmbossUpdateJob(std::unique_ptr input); void process(Ctl &ctl) override; void finalize(bool canceled, std::exception_ptr &) override; }; -class EmbossCreateJob : public Job + +/// +/// Create new TextVolume on the surface of ModelObject +/// +class EmbossCreateVolumeJob : public Job { - std::unique_ptr m_input; - TriangleMesh m_result; - Transform3d m_transformation; + std::unique_ptr m_input; + TriangleMesh m_result; + Transform3d m_transformation; + public: - EmbossCreateJob(std::unique_ptr input): m_input(std::move(input)){} + EmbossCreateVolumeJob(std::unique_ptr input); void process(Ctl &ctl) override; void finalize(bool canceled, std::exception_ptr &) override; - - // - /// Create mesh from text - /// - /// Text to convert on mesh - /// Define shape of characters. - /// NOTE: Can't be const cache glyphs - /// Property of font - /// Control for job, check of cancelation - /// Triangle mesh model - static TriangleMesh create_mesh(const char * text, - Emboss::FontFileWithCache &font, - const FontProp & font_prop, - Ctl & ctl); - -private: - static TriangleMesh create_default_mesh(); }; +/// +/// Create new TextObject on the platter +/// +class EmbossCreateObjectJob : public Job +{ + std::unique_ptr m_input; + TriangleMesh m_result; + Transform3d m_transformation; + +public: + EmbossCreateObjectJob(std::unique_ptr input); + void process(Ctl &ctl) override; + void finalize(bool canceled, std::exception_ptr &) override; +}; /// /// Base data holder for embossing @@ -98,9 +105,10 @@ struct EmbossDataUpdate : public EmbossDataBase }; /// -/// Hold neccessary data to create embossed text object in job +/// Hold neccessary data to create ModelVolume in job +/// Volume is created on the surface of existing volume in object. /// -struct EmbossDataCreate: public EmbossDataBase +struct EmbossDataCreateVolume : public EmbossDataBase { // define embossed volume type ModelVolumeType volume_type; @@ -108,11 +116,47 @@ struct EmbossDataCreate: public EmbossDataBase // define position on screen where to create object Vec2d screen_coor; - // when exist ModelObject where to create volume - std::optional object_idx; + // parent ModelObject index where to create volume + int object_idx; - // hitted instance transformation - std::optional hit_vol_tr; + // projection property + Camera camera; + + // used to find point on surface where to create new object + RaycastManager::SurfacePoint hit; + Transform3d hit_object_tr; + Transform3d hit_instance_tr; + + EmbossDataCreateVolume(Emboss::FontFileWithCache font_file, + const TextConfiguration &text_configuration, + const std::string &volume_name, + ModelVolumeType volume_type, + Vec2d screen_coor, + int object_idx, + const Camera &camera, + const RaycastManager::SurfacePoint &hit, + const Transform3d &hit_object_tr, + const Transform3d &hit_instance_tr) + : EmbossDataBase(font_file, text_configuration, volume_name) + , volume_type(volume_type) + , screen_coor(screen_coor) + , object_idx(object_idx) + , camera(camera) + , hit(hit) + , hit_object_tr(hit_object_tr) + , hit_instance_tr(hit_instance_tr) + {} +}; + +/// +/// Hold neccessary data to create ModelObject in job +/// Object is placed on bed under screen coor +/// OR to center of scene when it is out of bed shape +/// +struct EmbossDataCreateObject : public EmbossDataBase +{ + // define position on screen where to create object + Vec2d screen_coor; // projection property Camera camera; @@ -120,29 +164,16 @@ struct EmbossDataCreate: public EmbossDataBase // shape of bed in case of create volume on bed std::vector bed_shape; - // used to find point on surface where to create new object - RaycastManager *raycast_manager; - // It is inside of GLGizmoEmboss object, - // so I hope it will survive - - EmbossDataCreate(Emboss::FontFileWithCache font_file, - const TextConfiguration & text_configuration, - const std::string & volume_name, - ModelVolumeType volume_type, - Vec2d screen_coor, - std::optional object_idx, - const std::optional& hit_vol_tr, - const Camera& camera, - const std::vector & bed_shape, - RaycastManager * raycast_manager) + EmbossDataCreateObject(Emboss::FontFileWithCache font_file, + const TextConfiguration &text_configuration, + const std::string &volume_name, + Vec2d screen_coor, + const Camera &camera, + const std::vector &bed_shape) : EmbossDataBase(font_file, text_configuration, volume_name) - , volume_type(volume_type) , screen_coor(screen_coor) - , object_idx(object_idx) - , hit_vol_tr(hit_vol_tr) , camera(camera) , bed_shape(bed_shape) - , raycast_manager(raycast_manager) {} }; diff --git a/src/slic3r/Utils/RaycastManager.cpp b/src/slic3r/Utils/RaycastManager.cpp index 87a53a9788..12c340be4d 100644 --- a/src/slic3r/Utils/RaycastManager.cpp +++ b/src/slic3r/Utils/RaycastManager.cpp @@ -12,12 +12,12 @@ void RaycastManager::actualize(const ModelObjectPtrs &objects, { // check if volume was removed std::set removed_casters; - for (const auto &raycaster_item : raycasters) + for (const auto &raycaster_item : m_raycasters) removed_casters.insert(raycaster_item.first); // check if inscance was removed std::set removed_transformation; - for (const auto &item : transformations) + for (const auto &item : m_transformations) removed_transformation.insert(item.first); for (const ModelObject *object : objects) { @@ -28,8 +28,8 @@ void RaycastManager::actualize(const ModelObjectPtrs &objects, removed_casters.erase(oid); continue; } - auto item = raycasters.find(oid); - if (item != raycasters.end()) { + auto item = m_raycasters.find(oid); + if (item != m_raycasters.end()) { removed_casters.erase(oid); // alredy in list only actualize // TODO: check triangles when change than actualize MeshRaycaster @@ -37,7 +37,7 @@ void RaycastManager::actualize(const ModelObjectPtrs &objects, // add new raycaster auto raycaster = std::make_unique( volume->mesh()); - raycasters.insert(std::make_pair(oid, std::move(raycaster))); + m_raycasters.insert(std::make_pair(oid, std::move(raycaster))); } } @@ -52,14 +52,14 @@ void RaycastManager::actualize(const ModelObjectPtrs &objects, // transformation.translation()(2) += m_sla_shift_z; TrKey tr_key = std::make_pair(instance->id().id, volume->id().id); - auto item = transformations.find(tr_key); - if (item != transformations.end()) { + auto item = m_transformations.find(tr_key); + if (item != m_transformations.end()) { // actualize transformation all the time item->second = transformation; removed_transformation.erase(tr_key); } else { // add new transformation - transformations.insert( + m_transformations.insert( std::make_pair(tr_key, transformation)); } } @@ -67,10 +67,10 @@ void RaycastManager::actualize(const ModelObjectPtrs &objects, } // remove non existing volumes - for (size_t volume_oid : removed_casters) raycasters.erase(volume_oid); + for (size_t volume_oid : removed_casters) m_raycasters.erase(volume_oid); // remove non existing transformations for (const TrKey& transformation_key : removed_transformation) - transformations.erase(transformation_key); + m_transformations.erase(transformation_key); } void RaycastManager::actualize(const ModelObject *object, const ISkip *skip) @@ -80,11 +80,11 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip) size_t oid = volume->id().id; if (skip != nullptr && skip->skip(oid)) continue; - auto item = raycasters.find(oid); - if (item == raycasters.end()) { + auto item = m_raycasters.find(oid); + if (item == m_raycasters.end()) { // add new raycaster auto raycaster = std::make_unique(volume->mesh()); - raycasters.insert(std::make_pair(oid, std::move(raycaster))); + m_raycasters.insert(std::make_pair(oid, std::move(raycaster))); } } @@ -98,13 +98,14 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip) // TODO: add SLA shift Z // transformation.translation()(2) += m_sla_shift_z; TrKey tr_key = std::make_pair(instance->id().id, volume->id().id); - auto item = transformations.find(tr_key); - if (item != transformations.end()) { + auto item = m_transformations.find(tr_key); + if (item != m_transformations.end()) { // actualize transformation all the time item->second = transformation; } else { // add new transformation - transformations.insert(std::make_pair(tr_key, transformation)); + m_transformations.insert( + std::make_pair(tr_key, transformation)); } } } @@ -124,13 +125,13 @@ std::optional RaycastManager::unproject( {} }; std::optional closest; - for (const auto &item : transformations) { + for (const auto &item : m_transformations) { const TrKey &key = item.first; size_t volume_id = key.second; if (skip != nullptr && skip->skip(volume_id)) continue; const Transform3d &transformation = item.second; - auto raycaster_it = raycasters.find(volume_id); - if (raycaster_it == raycasters.end()) continue; + auto raycaster_it = m_raycasters.find(volume_id); + if (raycaster_it == m_raycasters.end()) continue; const MeshRaycaster &raycaster = *(raycaster_it->second); SurfacePoint surface_point; bool success = raycaster.unproject_on_mesh( @@ -151,7 +152,7 @@ std::optional RaycastManager::unproject( } Slic3r::Transform3d RaycastManager::get_transformation(const TrKey &tr_key) const { - auto item = transformations.find(tr_key); - if (item == transformations.end()) return Transform3d::Identity(); + auto item = m_transformations.find(tr_key); + if (item == m_transformations.end()) return Transform3d::Identity(); return item->second; } \ No newline at end of file diff --git a/src/slic3r/Utils/RaycastManager.hpp b/src/slic3r/Utils/RaycastManager.hpp index 5edfa35aa0..ba0736258d 100644 --- a/src/slic3r/Utils/RaycastManager.hpp +++ b/src/slic3r/Utils/RaycastManager.hpp @@ -11,19 +11,23 @@ namespace Slic3r::GUI{ +/// +/// Cast rays from camera to scene +/// Used for find hit point on model volume under mouse cursor +/// class RaycastManager { - // ModelVolume - std::map> raycasters; + // ModelVolume + std::map> m_raycasters; // Key for transformation consist of unique volume and instance // ModelInstance, ModelVolume using TrKey = std::pair; - std::map transformations; + std::map m_transformations; // should contain shared pointer to camera but it is not shared pointer so it need it every time when casts rays -public: +public: class ISkip{ public: virtual ~ISkip() = default;