diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
index 7bf9635a4d..a0a367d938 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
@@ -345,16 +345,6 @@ bool GLGizmoEmboss::on_mouse_for_rotation(const wxMouseEvent &mouse_event)
}
namespace priv {
-///
-/// Get transformation to world
-/// - use fix after store to 3mf when exists
-///
-/// Scene volume
-/// To identify MovelVolume with fix transformation
-///
-static Transform3d world_matrix(const GLVolume *gl_volume, const Model *model);
-static Transform3d world_matrix(const Selection &selection);
-
///
/// Change position of emboss window
///
@@ -363,36 +353,6 @@ static Transform3d world_matrix(const Selection &selection);
static void change_window_position(std::optional &output_window_offset, bool try_to_fix);
} // namespace priv
-Transform3d priv::world_matrix(const GLVolume *gl_volume, const Model *model)
-{
- if (!gl_volume)
- return Transform3d::Identity();
- Transform3d res = gl_volume->world_matrix();
-
- if (!model)
- return res;
-
- const ModelVolume* mv = get_model_volume(*gl_volume, model->objects);
- if (!mv)
- return res;
-
- const std::optional &tc = mv->text_configuration;
- if (!tc.has_value())
- return res;
-
- const std::optional &fix = tc->fix_3mf_tr;
- if (!fix.has_value())
- return res;
-
- return res * fix->inverse();
-}
-
-Transform3d priv::world_matrix(const Selection &selection)
-{
- const GLVolume *gl_volume = get_selected_gl_volume(selection);
- return world_matrix(gl_volume, selection.get_model());
-}
-
bool GLGizmoEmboss::on_mouse_for_translate(const wxMouseEvent &mouse_event)
{
// exist selected volume?
@@ -1115,17 +1075,6 @@ static inline void execute_job(std::shared_ptr j)
});
}
-namespace priv {
-///
-/// Calculate translation of text volume onto surface of model
-///
-/// Text
-/// AABB trees of object. Actualize object containing text
-/// Transformation of actual instance
-/// Offset of volume in volume coordinate
-std::optional calc_surface_offset(const ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection);
-} // namespace priv
-
bool GLGizmoEmboss::process()
{
// no volume is selected -> selection from right panel
@@ -1160,7 +1109,7 @@ bool GLGizmoEmboss::process()
// when it is new applying of use surface than move origin onto surfaca
if (!m_volume->text_configuration->style.prop.use_surface) {
- auto offset = priv::calc_surface_offset(*m_volume, m_raycast_manager, m_parent.get_selection());
+ auto offset = calc_surface_offset(m_parent.get_selection(), m_raycast_manager);
if (offset.has_value())
text_tr *= Eigen::Translation(*offset);
}
@@ -1231,7 +1180,7 @@ bool priv::apply_camera_dir(const Camera &camera, GLCanvas3D &canvas) {
if (sel.is_empty()) return false;
// camera direction transformed into volume coordinate system
- Transform3d to_world = priv::world_matrix(sel);
+ Transform3d to_world = world_matrix_fixed(sel);
Vec3d cam_dir_tr = to_world.inverse().linear() * cam_dir;
cam_dir_tr.normalize();
@@ -2949,53 +2898,6 @@ void GLGizmoEmboss::do_rotate(float relative_z_angle)
m_parent.do_rotate(snapshot_name);
}
-std::optional priv::calc_surface_offset(const ModelVolume &volume, RaycastManager &raycast_manager, const Selection &selection) {
- // Move object on surface
- auto cond = RaycastManager::SkipVolume(volume.id().id);
- raycast_manager.actualize(volume.get_object(), &cond);
-
- //const Selection &selection = m_parent.get_selection();
- const GLVolume *gl_volume = get_selected_gl_volume(selection);
- Transform3d to_world = priv::world_matrix(gl_volume, selection.get_model());
- Vec3d point = to_world * Vec3d::Zero();
- Vec3d direction = to_world.linear() * (-Vec3d::UnitZ());
-
- // ray in direction of text projection(from volume zero to z-dir)
- std::optional hit_opt = raycast_manager.closest_hit(point, direction, &cond);
-
- // Try to find closest point when no hit object in emboss direction
- if (!hit_opt.has_value()) {
- std::optional close_point_opt = raycast_manager.closest(point);
-
- // It should NOT appear. Closest point always exists.
- assert(close_point_opt.has_value());
- if (!close_point_opt.has_value())
- return {};
-
- // It is no neccesary to move with origin by very small value
- if (close_point_opt->squared_distance < EPSILON)
- return {};
-
- const RaycastManager::ClosePoint &close_point = *close_point_opt;
- Transform3d hit_tr = raycast_manager.get_transformation(close_point.tr_key);
- Vec3d hit_world = hit_tr * close_point.point;
- Vec3d offset_world = hit_world - point; // vector in world
- Vec3d offset_volume = to_world.inverse().linear() * offset_world;
- return offset_volume;
- }
-
- // It is no neccesary to move with origin by very small value
- const RaycastManager::Hit &hit = *hit_opt;
- if (hit.squared_distance < EPSILON)
- return {};
- Transform3d hit_tr = raycast_manager.get_transformation(hit.tr_key);
- Vec3d hit_world = hit_tr * hit.position;
- Vec3d offset_world = hit_world - point; // vector in world
- // TIP: It should be close to only z move
- Vec3d offset_volume = to_world.inverse().linear() * offset_world;
- return offset_volume;
-}
-
void GLGizmoEmboss::draw_advanced()
{
const auto &ff = m_style_manager.get_font_file_with_cache();
@@ -3610,7 +3512,7 @@ bool priv::start_create_volume_on_surface_job(
auto cond = RaycastManager::AllowVolumes({vol_id});
RaycastManager::Meshes meshes = create_meshes(canvas, cond);
- raycaster.actualize(obj, &cond, &meshes);
+ raycaster.actualize(*obj, &cond, &meshes);
const Camera &camera = plater->get_camera();
std::optional hit = ray_from_camera(raycaster, screen_coor, camera, &cond);
diff --git a/src/slic3r/GUI/SurfaceDrag.cpp b/src/slic3r/GUI/SurfaceDrag.cpp
index 46b6121588..33f64c0c61 100644
--- a/src/slic3r/GUI/SurfaceDrag.cpp
+++ b/src/slic3r/GUI/SurfaceDrag.cpp
@@ -104,11 +104,14 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
gl_volumes[hovered_idx] != gl_volume)
return false;
- const ModelObject *object = get_model_object(*gl_volume, canvas.get_model()->objects);
+ const ModelObject *object = get_model_object(*gl_volume, canvas.get_model()->objects);
+ assert(object != nullptr);
+ if (object == nullptr)
+ return false;
+
const ModelInstance *instance = get_model_instance(*gl_volume, *object);
const ModelVolume *volume = get_model_volume(*gl_volume, *object);
-
- assert(object != nullptr && instance != nullptr && volume != nullptr);
+ assert(instance != nullptr && volume != nullptr);
if (object == nullptr || instance == nullptr || volume == nullptr)
return false;
@@ -131,7 +134,7 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
// initialize raycasters
// INFO: It could slows down for big objects
// (may be move to thread and do not show drag until it finish)
- raycast_manager.actualize(instance, &condition, &meshes);
+ raycast_manager.actualize(*instance, &condition, &meshes);
// wxCoord == int --> wx/types.h
Vec2i mouse_coord(mouse_event.GetX(), mouse_event.GetY());
@@ -242,4 +245,92 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
return false;
}
+std::optional calc_surface_offset(const Selection &selection, RaycastManager &raycast_manager) {
+ const GLVolume *gl_volume_ptr = get_selected_gl_volume(selection);
+ if (gl_volume_ptr == nullptr)
+ return {};
+ const GLVolume& gl_volume = *gl_volume_ptr;
+
+ const ModelObjectPtrs &objects = selection.get_model()->objects;
+ const ModelVolume* volume = get_model_volume(gl_volume, objects);
+ if (volume == nullptr)
+ return {};
+
+ const ModelInstance* instance = get_model_instance(gl_volume, objects);
+ if (instance == nullptr)
+ return {};
+
+ // Move object on surface
+ auto cond = RaycastManager::SkipVolume(volume->id().id);
+ raycast_manager.actualize(*instance, &cond);
+
+ Transform3d to_world = world_matrix_fixed(gl_volume, selection.get_model()->objects);
+ Vec3d point = to_world * Vec3d::Zero();
+ Vec3d direction = to_world.linear() * (-Vec3d::UnitZ());
+
+ // ray in direction of text projection(from volume zero to z-dir)
+ std::optional hit_opt = raycast_manager.closest_hit(point, direction, &cond);
+
+ // Try to find closest point when no hit object in emboss direction
+ if (!hit_opt.has_value()) {
+ std::optional close_point_opt = raycast_manager.closest(point);
+
+ // It should NOT appear. Closest point always exists.
+ assert(close_point_opt.has_value());
+ if (!close_point_opt.has_value())
+ return {};
+
+ // It is no neccesary to move with origin by very small value
+ if (close_point_opt->squared_distance < EPSILON)
+ return {};
+
+ const RaycastManager::ClosePoint &close_point = *close_point_opt;
+ Transform3d hit_tr = raycast_manager.get_transformation(close_point.tr_key);
+ Vec3d hit_world = hit_tr * close_point.point;
+ Vec3d offset_world = hit_world - point; // vector in world
+ Vec3d offset_volume = to_world.inverse().linear() * offset_world;
+ return offset_volume;
+ }
+
+ // It is no neccesary to move with origin by very small value
+ const RaycastManager::Hit &hit = *hit_opt;
+ if (hit.squared_distance < EPSILON)
+ return {};
+ Transform3d hit_tr = raycast_manager.get_transformation(hit.tr_key);
+ Vec3d hit_world = hit_tr * hit.position;
+ Vec3d offset_world = hit_world - point; // vector in world
+ // TIP: It should be close to only z move
+ Vec3d offset_volume = to_world.inverse().linear() * offset_world;
+ return offset_volume;
+}
+
+Transform3d world_matrix_fixed(const GLVolume &gl_volume, const ModelObjectPtrs &objects)
+{
+ Transform3d res = gl_volume.world_matrix();
+
+ const ModelVolume *mv = get_model_volume(gl_volume, objects);
+ if (!mv)
+ return res;
+
+ const std::optional &tc = mv->text_configuration;
+ if (!tc.has_value())
+ return res;
+
+ const std::optional &fix = tc->fix_3mf_tr;
+ if (!fix.has_value())
+ return res;
+
+ return res * fix->inverse();
+}
+
+Transform3d world_matrix_fixed(const Selection &selection)
+{
+ const GLVolume *gl_volume = get_selected_gl_volume(selection);
+ assert(gl_volume != nullptr);
+ if (gl_volume == nullptr)
+ return Transform3d::Identity();
+
+ return world_matrix_fixed(*gl_volume, selection.get_model()->objects);
+}
+
} // namespace Slic3r::GUI
\ No newline at end of file
diff --git a/src/slic3r/GUI/SurfaceDrag.hpp b/src/slic3r/GUI/SurfaceDrag.hpp
index c3dc9cd2db..a3765f86bf 100644
--- a/src/slic3r/GUI/SurfaceDrag.hpp
+++ b/src/slic3r/GUI/SurfaceDrag.hpp
@@ -12,6 +12,7 @@ class GLVolume;
namespace Slic3r::GUI {
class GLCanvas3D;
+class Selection;
struct Camera;
// Data for drag&drop over surface with mouse
@@ -37,11 +38,48 @@ struct SurfaceDrag
bool exist_hit = true;
};
+///
+/// Mouse event handler, when move(drag&drop) volume over model surface
+/// NOTE: Dragged volume has to be selected. And also has to be hovered on start of dragging.
+///
+/// Contain type of event and mouse position
+/// Actual viewport of camera
+/// Structure which keep information about dragging
+/// Contain gl_volumes and selection
+/// AABB trees for raycast in object
+/// Refresh state inside of function
+/// True when event is processed otherwise false
bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
const Camera &camera,
std::optional &surface_drag,
GLCanvas3D &canvas,
RaycastManager &raycast_manager);
+///
+/// Calculate translation of volume onto surface of model
+///
+/// Must contain only one selected volume, Transformation of current instance
+/// AABB trees of object. Actualize object
+/// Offset of volume in volume coordinate
+std::optional calc_surface_offset(const Selection &selection, RaycastManager &raycast_manager);
+
+///
+/// Get transformation to world
+/// - use fix after store to 3mf when exists
+///
+/// Scene volume
+/// To identify Model volume with fix transformation
+/// Fixed Transformation of gl_volume
+Transform3d world_matrix_fixed(const GLVolume &gl_volume, const ModelObjectPtrs& objects);
+
+///
+/// Get transformation to world
+/// - use fix after store to 3mf when exists
+/// NOTE: when not one volume selected return identity
+///
+/// Selected volume
+/// Fixed Transformation of selected volume in selection
+Transform3d world_matrix_fixed(const Selection &selection);
+
} // namespace Slic3r::GUI
#endif // slic3r_SurfaceDrag_hpp_
\ No newline at end of file
diff --git a/src/slic3r/Utils/RaycastManager.cpp b/src/slic3r/Utils/RaycastManager.cpp
index 18c9bb2f19..63cb580dbe 100644
--- a/src/slic3r/Utils/RaycastManager.cpp
+++ b/src/slic3r/Utils/RaycastManager.cpp
@@ -7,8 +7,8 @@ namespace priv {
using namespace Slic3r;
static void actualize(RaycastManager::Meshes &meshes, const ModelVolumePtrs &volumes, const RaycastManager::ISkip *skip, RaycastManager::Meshes *input = nullptr);
static const AABBMesh * get_mesh(const RaycastManager::Meshes &meshes, size_t volume_id);
-static RaycastManager::TrKey create_key(const ModelVolume* volume, const ModelInstance* instance){
- return std::make_pair(instance->id().id, volume->id().id); }
+static RaycastManager::TrKey create_key(const ModelVolume& volume, const ModelInstance& instance){
+ return std::make_pair(instance.id().id, volume.id().id); }
static RaycastManager::TrItems::iterator find(RaycastManager::TrItems &items, const RaycastManager::TrKey &key);
static bool is_lower_key(const RaycastManager::TrKey &k1, const RaycastManager::TrKey &k2) {
return k1.first < k2.first || k1.first == k2.first && k1.second < k2.second; }
@@ -16,23 +16,23 @@ static bool is_lower(const RaycastManager::TrItem &i1, const RaycastManager::TrI
return is_lower_key(i1.first, i2.first); };
}
-void RaycastManager::actualize(const ModelObject *object, const ISkip *skip, Meshes *meshes)
+void RaycastManager::actualize(const ModelObject &object, const ISkip *skip, Meshes *meshes)
{
// actualize MeshRaycaster
- priv::actualize(m_meshes, object->volumes, skip, meshes);
+ priv::actualize(m_meshes, object.volumes, skip, meshes);
// check if inscance was removed
std::vector removed_transf(m_transformations.size(), {true});
bool need_sort = false;
// actualize transformation matrices
- for (const ModelVolume *volume : object->volumes) {
+ for (const ModelVolume *volume : object.volumes) {
if (skip != nullptr && skip->skip(volume->id().id)) continue;
const Transform3d &volume_tr = volume->get_matrix();
- for (const ModelInstance *instance : object->instances) {
+ for (const ModelInstance *instance : object.instances) {
const Transform3d &instrance_tr = instance->get_matrix();
Transform3d transformation = instrance_tr * volume_tr;
- TrKey key = priv::create_key(volume, instance);
+ TrKey key = priv::create_key(*volume, *instance);
auto item = priv::find(m_transformations, key);
if (item != m_transformations.end()) {
// actualize transformation all the time
@@ -56,9 +56,9 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip, Mes
std::sort(m_transformations.begin(), m_transformations.end(), priv::is_lower);
}
-void RaycastManager::actualize(const ModelInstance *instance, const ISkip *skip, Meshes *meshes)
+void RaycastManager::actualize(const ModelInstance &instance, const ISkip *skip, Meshes *meshes)
{
- const ModelVolumePtrs &volumes = instance->get_object()->volumes;
+ const ModelVolumePtrs &volumes = instance.get_object()->volumes;
// actualize MeshRaycaster
priv::actualize(m_meshes, volumes, skip, meshes);
@@ -72,9 +72,9 @@ void RaycastManager::actualize(const ModelInstance *instance, const ISkip *skip,
if (skip != nullptr && skip->skip(volume->id().id))
continue;
const Transform3d &volume_tr = volume->get_matrix();
- const Transform3d &instrance_tr = instance->get_matrix();
+ const Transform3d &instrance_tr = instance.get_matrix();
Transform3d transformation = instrance_tr * volume_tr;
- TrKey key = priv::create_key(volume, instance);
+ TrKey key = priv::create_key(*volume, instance);
auto item = priv::find(m_transformations, key);
if (item != m_transformations.end()) {
// actualize transformation all the time
diff --git a/src/slic3r/Utils/RaycastManager.hpp b/src/slic3r/Utils/RaycastManager.hpp
index a3cd3ef910..41ec82d6c8 100644
--- a/src/slic3r/Utils/RaycastManager.hpp
+++ b/src/slic3r/Utils/RaycastManager.hpp
@@ -86,8 +86,8 @@ public:
/// Model representation
/// Condifiton for skip actualization
/// Speed up for already created AABBtrees
- void actualize(const ModelObject *object, const ISkip *skip = nullptr, Meshes *meshes = nullptr);
- void actualize(const ModelInstance *instance, const ISkip *skip = nullptr, Meshes* meshes = nullptr);
+ void actualize(const ModelObject &object, const ISkip *skip = nullptr, Meshes *meshes = nullptr);
+ void actualize(const ModelInstance &instance, const ISkip *skip = nullptr, Meshes* meshes = nullptr);
class SkipVolume: public ISkip
{