Gizmo measure modified to accept single full instance selection, to combine the volumes meshes into a single mesh and pass it to the back end after transform it in world coordinates

Changes embedded into tech ENABLE_GIZMO_MEASURE_WORLD_COORDINATES

Fixed conflicts during rebase to master
This commit is contained in:
enricoturri1966 2022-11-15 12:17:18 +01:00
parent 33949734e3
commit fc2f0bad6e
9 changed files with 347 additions and 13 deletions

View File

@ -47,6 +47,9 @@ public:
std::optional<SurfaceFeature> get_feature(size_t face_idx, const Vec3d& point) const; std::optional<SurfaceFeature> get_feature(size_t face_idx, const Vec3d& point) const;
std::vector<std::vector<int>> get_planes_triangle_indices() const; std::vector<std::vector<int>> get_planes_triangle_indices() const;
const std::vector<SurfaceFeature>& get_plane_features(unsigned int plane_id) const; const std::vector<SurfaceFeature>& get_plane_features(unsigned int plane_id) const;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const TriangleMesh& get_mesh() const;
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
private: private:
void update_planes(); void update_planes();
@ -54,7 +57,11 @@ private:
std::vector<PlaneData> m_planes; std::vector<PlaneData> m_planes;
std::vector<size_t> m_face_to_plane; std::vector<size_t> m_face_to_plane;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
TriangleMesh m_mesh;
#else
const indexed_triangle_set& m_its; const indexed_triangle_set& m_its;
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
}; };
@ -63,7 +70,11 @@ private:
MeasuringImpl::MeasuringImpl(const indexed_triangle_set& its) MeasuringImpl::MeasuringImpl(const indexed_triangle_set& its)
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
: m_mesh(its)
#else
: m_its{its} : m_its{its}
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
{ {
update_planes(); update_planes();
extract_features(); extract_features();
@ -76,10 +87,17 @@ void MeasuringImpl::update_planes()
// Now we'll go through all the facets and append Points of facets sharing the same normal. // Now we'll go through all the facets and append Points of facets sharing the same normal.
// This part is still performed in mesh coordinate system. // This part is still performed in mesh coordinate system.
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const size_t num_of_facets = m_mesh.its.indices.size();
m_face_to_plane.resize(num_of_facets, size_t(-1));
const std::vector<Vec3f> face_normals = its_face_normals(m_mesh.its);
const std::vector<Vec3i> face_neighbors = its_face_neighbors(m_mesh.its);
#else
const size_t num_of_facets = m_its.indices.size(); const size_t num_of_facets = m_its.indices.size();
m_face_to_plane.resize(num_of_facets, size_t(-1)); m_face_to_plane.resize(num_of_facets, size_t(-1));
const std::vector<Vec3f> face_normals = its_face_normals(m_its); const std::vector<Vec3f> face_normals = its_face_normals(m_its);
const std::vector<Vec3i> face_neighbors = its_face_neighbors(m_its); const std::vector<Vec3i> face_neighbors = its_face_neighbors(m_its);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
std::vector<int> facet_queue(num_of_facets, 0); std::vector<int> facet_queue(num_of_facets, 0);
int facet_queue_cnt = 0; int facet_queue_cnt = 0;
const stl_normal* normal_ptr = nullptr; const stl_normal* normal_ptr = nullptr;
@ -128,7 +146,11 @@ void MeasuringImpl::update_planes()
assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); })); assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); }));
// Now we will walk around each of the planes and save vertices which form the border. // Now we will walk around each of the planes and save vertices which form the border.
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
SurfaceMesh sm(m_mesh.its);
#else
SurfaceMesh sm(m_its); SurfaceMesh sm(m_its);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) { for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) {
const auto& facets = m_planes[plane_id].facets; const auto& facets = m_planes[plane_id].facets;
m_planes[plane_id].borders.clear(); m_planes[plane_id].borders.clear();
@ -510,6 +532,12 @@ const std::vector<SurfaceFeature>& MeasuringImpl::get_plane_features(unsigned in
return m_planes[plane_id].surface_features; return m_planes[plane_id].surface_features;
} }
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const TriangleMesh& MeasuringImpl::get_mesh() const
{
return this->m_mesh;
}
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
@ -551,6 +579,13 @@ const std::vector<SurfaceFeature>& Measuring::get_plane_features(unsigned int pl
return priv->get_plane_features(plane_id); return priv->get_plane_features(plane_id);
} }
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const TriangleMesh& Measuring::get_mesh() const
{
return priv->get_mesh();
}
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const AngleAndEdges AngleAndEdges::Dummy = { 0.0, Vec3d::Zero(), { Vec3d::Zero(), Vec3d::Zero() }, { Vec3d::Zero(), Vec3d::Zero() }, 0.0, true }; const AngleAndEdges AngleAndEdges::Dummy = { 0.0, Vec3d::Zero(), { Vec3d::Zero(), Vec3d::Zero() }, { Vec3d::Zero(), Vec3d::Zero() }, 0.0, true };
static AngleAndEdges angle_edge_edge(const std::pair<Vec3d, Vec3d>& e1, const std::pair<Vec3d, Vec3d>& e2) static AngleAndEdges angle_edge_edge(const std::pair<Vec3d, Vec3d>& e1, const std::pair<Vec3d, Vec3d>& e2)
@ -1149,6 +1184,7 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature&
return result; return result;
} }
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void DistAndPoints::transform(const Transform3d& trafo) { void DistAndPoints::transform(const Transform3d& trafo) {
from = trafo * from; from = trafo * from;
to = trafo * to; to = trafo * to;
@ -1169,6 +1205,7 @@ void AngleAndEdges::transform(const Transform3d& trafo) {
const double average_scale = 0.5 * (new_e1.norm() / old_e1.norm() + new_e2.norm() / old_e2.norm()); const double average_scale = 0.5 * (new_e1.norm() / old_e1.norm() + new_e2.norm() / old_e2.norm());
radius = average_scale * radius; radius = average_scale * radius;
} }
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES

View File

@ -87,8 +87,10 @@ class MeasuringImpl;
class Measuring { class Measuring {
public: public:
// Construct the measurement object on a given its. The its must remain // Construct the measurement object on a given its.
// valid and unchanged during the whole lifetime of the object. #if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
// The its must remain valid and unchanged during the whole lifetime of the object.
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
explicit Measuring(const indexed_triangle_set& its); explicit Measuring(const indexed_triangle_set& its);
~Measuring(); ~Measuring();
@ -108,6 +110,11 @@ public:
// Returns the surface features of the plane with the given index // Returns the surface features of the plane with the given index
const std::vector<SurfaceFeature>& get_plane_features(unsigned int plane_id) const; const std::vector<SurfaceFeature>& get_plane_features(unsigned int plane_id) const;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
// Returns the mesh used for measuring
const TriangleMesh& get_mesh() const;
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
private: private:
std::unique_ptr<MeasuringImpl> priv; std::unique_ptr<MeasuringImpl> priv;
}; };
@ -119,7 +126,9 @@ struct DistAndPoints {
Vec3d from; Vec3d from;
Vec3d to; Vec3d to;
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void transform(const Transform3d& trafo); void transform(const Transform3d& trafo);
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
}; };
struct AngleAndEdges { struct AngleAndEdges {
@ -132,7 +141,9 @@ struct AngleAndEdges {
double radius; double radius;
bool coplanar; bool coplanar;
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void transform(const Transform3d& trafo); void transform(const Transform3d& trafo);
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
static const AngleAndEdges Dummy; static const AngleAndEdges Dummy;
}; };
@ -151,6 +162,7 @@ struct MeasurementResult {
return angle.has_value() || distance_infinite.has_value() || distance_strict.has_value() || distance_xyz.has_value(); return angle.has_value() || distance_infinite.has_value() || distance_strict.has_value() || distance_xyz.has_value();
} }
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void transform(const Transform3d& trafo) { void transform(const Transform3d& trafo) {
if (angle.has_value()) if (angle.has_value())
angle->transform(trafo); angle->transform(trafo);
@ -161,6 +173,7 @@ struct MeasurementResult {
distance_xyz = (distance_strict->to - distance_strict->from).cwiseAbs(); distance_xyz = (distance_strict->to - distance_strict->from).cwiseAbs();
} }
} }
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
}; };
// Returns distance/angle between two SurfaceFeatures. // Returns distance/angle between two SurfaceFeatures.

View File

@ -64,6 +64,8 @@
// Enable picking using raytracing // Enable picking using raytracing
#define ENABLE_RAYCAST_PICKING (1 && ENABLE_LEGACY_OPENGL_REMOVAL) #define ENABLE_RAYCAST_PICKING (1 && ENABLE_LEGACY_OPENGL_REMOVAL)
#define ENABLE_RAYCAST_PICKING_DEBUG (0 && ENABLE_RAYCAST_PICKING) #define ENABLE_RAYCAST_PICKING_DEBUG (0 && ENABLE_RAYCAST_PICKING)
// Enable gizmo measure combining volumes meshes and passing them to the backend in world coordinates
#define ENABLE_GIZMO_MEASURE_WORLD_COORDINATES (1 && ENABLE_2_5_0_ALPHA1)
#endif // _prusaslicer_technologies_h_ #endif // _prusaslicer_technologies_h_

View File

@ -5,9 +5,11 @@
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include "libslic3r/MeasureUtils.hpp" #include "libslic3r/MeasureUtils.hpp"
@ -242,7 +244,10 @@ private:
TransformHelper::Cache TransformHelper::s_cache = { { 0, 0, 0, 0 }, Matrix4d::Identity(), Transform3d::Identity() }; TransformHelper::Cache TransformHelper::s_cache = { { 0, 0, 0, 0 }, Matrix4d::Identity(), Transform3d::Identity() };
GLGizmoMeasure::GLGizmoMeasure(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoMeasure::GLGizmoMeasure(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id)
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
, m_raycaster(nullptr)
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
{ {
GLModel::Geometry sphere_geometry = smooth_sphere(16, 7.5f); GLModel::Geometry sphere_geometry = smooth_sphere(16, 7.5f);
m_sphere.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(sphere_geometry.get_as_indexed_triangle_set())); m_sphere.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(sphere_geometry.get_as_indexed_triangle_set()));
@ -370,8 +375,10 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
if (m_selected_features != selected_features_old && m_selected_features.second.feature.has_value()) { if (m_selected_features != selected_features_old && m_selected_features.second.feature.has_value()) {
m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get());
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
// transform to world coordinates // transform to world coordinates
m_measurement_result.transform(m_volume_matrix); m_measurement_result.transform(m_volume_matrix);
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
} }
m_imgui->set_requires_extra_frame(); m_imgui->set_requires_extra_frame();
@ -419,6 +426,9 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
void GLGizmoMeasure::data_changed() void GLGizmoMeasure::data_changed()
{ {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
update_if_needed();
#else
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
const ModelObject* model_object = nullptr; const ModelObject* model_object = nullptr;
const ModelVolume* model_volume = nullptr; const ModelVolume* model_volume = nullptr;
@ -429,13 +439,16 @@ void GLGizmoMeasure::data_changed()
} }
if (model_object != m_old_model_object || model_volume != m_old_model_volume) if (model_object != m_old_model_object || model_volume != m_old_model_volume)
update_if_needed(); update_if_needed();
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
m_last_inv_zoom = 0.0f; m_last_inv_zoom = 0.0f;
m_last_plane_idx = -1; m_last_plane_idx = -1;
if (m_pending_scale) { if (m_pending_scale) {
m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get());
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
// transform to world coordinates // transform to world coordinates
m_measurement_result.transform(m_volume_matrix); m_measurement_result.transform(m_volume_matrix);
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
m_pending_scale = false; m_pending_scale = false;
} }
else else
@ -512,6 +525,9 @@ void GLGizmoMeasure::on_set_state()
m_editing_distance = false; m_editing_distance = false;
m_is_editing_distance_first_frame = true; m_is_editing_distance_first_frame = true;
m_measuring.reset(); m_measuring.reset();
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
m_raycaster.release();
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
} }
else { else {
m_mode = EMode::FeatureSelection; m_mode = EMode::FeatureSelection;
@ -528,10 +544,12 @@ void GLGizmoMeasure::on_set_state()
} }
} }
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
CommonGizmosDataID GLGizmoMeasure::on_get_requirements() const CommonGizmosDataID GLGizmoMeasure::on_get_requirements() const
{ {
return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::Raycaster)); return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::Raycaster));
} }
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
std::string GLGizmoMeasure::on_get_name() const std::string GLGizmoMeasure::on_get_name() const
{ {
@ -543,9 +561,15 @@ bool GLGizmoMeasure::on_is_activable() const
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
bool res = (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) ? bool res = (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) ?
selection.is_single_full_instance() : selection.is_single_full_instance() :
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier();
if (res)
res &= !selection.contains_sinking_volumes();
#else
selection.is_single_volume() || selection.is_single_volume_instance(); selection.is_single_volume() || selection.is_single_volume_instance();
if (res) if (res)
res &= !selection.get_first_volume()->is_sinking(); res &= !selection.get_first_volume()->is_sinking();
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
return res; return res;
} }
@ -562,8 +586,10 @@ void GLGizmoMeasure::on_render()
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
if ((wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA && selection.is_single_full_instance()) || if ((wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA && selection.is_single_full_instance()) ||
(selection.is_single_volume() || selection.is_single_volume_instance())) { (selection.is_single_volume() || selection.is_single_volume_instance())) {
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
update_if_needed(); update_if_needed();
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
@ -572,7 +598,11 @@ void GLGizmoMeasure::on_render()
Vec3f position_on_model; Vec3f position_on_model;
Vec3f normal_on_model; Vec3f normal_on_model;
size_t model_facet_idx; size_t model_facet_idx;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const bool mouse_on_object = m_raycaster.raycaster()->unproject_on_mesh(m_mouse_pos, Transform3d::Identity(), camera, position_on_model, normal_on_model, nullptr, &model_facet_idx);
#else
const bool mouse_on_object = m_c->raycaster()->raycasters().front()->unproject_on_mesh(m_mouse_pos, m_volume_matrix, camera, position_on_model, normal_on_model, nullptr, &model_facet_idx); const bool mouse_on_object = m_c->raycaster()->raycasters().front()->unproject_on_mesh(m_mouse_pos, m_volume_matrix, camera, position_on_model, normal_on_model, nullptr, &model_facet_idx);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const bool is_hovering_on_feature = (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection) && m_hover_id != -1; const bool is_hovering_on_feature = (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection) && m_hover_id != -1;
auto update_circle = [this, inv_zoom]() { auto update_circle = [this, inv_zoom]() {
@ -581,7 +611,11 @@ void GLGizmoMeasure::on_render()
m_last_circle = m_curr_feature; m_last_circle = m_curr_feature;
m_circle.reset(); m_circle.reset();
const auto [center, radius, normal] = m_curr_feature->get_circle(); const auto [center, radius, normal] = m_curr_feature->get_circle();
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), Transform3f::Identity());
#else
GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), m_volume_matrix.cast<float>()); GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), m_volume_matrix.cast<float>());
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
m_circle.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(circle_geometry.get_as_indexed_triangle_set())); m_circle.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(circle_geometry.get_as_indexed_triangle_set()));
m_circle.model.init_from(std::move(circle_geometry)); m_circle.model.init_from(std::move(circle_geometry));
return true; return true;
@ -639,7 +673,11 @@ void GLGizmoMeasure::on_render()
const auto [idx, normal, point] = m_curr_feature->get_plane(); const auto [idx, normal, point] = m_curr_feature->get_plane();
if (m_last_plane_idx != idx) { if (m_last_plane_idx != idx) {
m_last_plane_idx = idx; m_last_plane_idx = idx;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const indexed_triangle_set& its = m_measuring->get_mesh().its;
#else
const indexed_triangle_set its = (m_old_model_volume != nullptr) ? m_old_model_volume->mesh().its : m_old_model_object->volumes.front()->mesh().its; const indexed_triangle_set its = (m_old_model_volume != nullptr) ? m_old_model_volume->mesh().its : m_old_model_object->volumes.front()->mesh().its;
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const std::vector<std::vector<int>> planes_triangles = m_measuring->get_planes_triangle_indices(); const std::vector<std::vector<int>> planes_triangles = m_measuring->get_planes_triangle_indices();
GLModel::Geometry init_data = init_plane_data(its, planes_triangles, idx); GLModel::Geometry init_data = init_plane_data(its, planes_triangles, idx);
m_plane.reset(); m_plane.reset();
@ -689,12 +727,20 @@ void GLGizmoMeasure::on_render()
if (extra.has_value() && m_hover_id == POINT_ID) if (extra.has_value() && m_hover_id == POINT_ID)
m_curr_point_on_feature_position = *extra; m_curr_point_on_feature_position = *extra;
else else
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
m_curr_point_on_feature_position = position_on_feature(EDGE_ID, camera, [](const Vec3f& v) { return Vec3f(0.0f, 0.0f, v.z()); });
#else
m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(EDGE_ID, camera, [](const Vec3f& v) { return Vec3f(0.0f, 0.0f, v.z()); }); m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(EDGE_ID, camera, [](const Vec3f& v) { return Vec3f(0.0f, 0.0f, v.z()); });
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
break; break;
} }
case Measure::SurfaceFeatureType::Plane: case Measure::SurfaceFeatureType::Plane:
{ {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
m_curr_point_on_feature_position = position_on_feature(PLANE_ID, camera);
#else
m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(PLANE_ID, camera); m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(PLANE_ID, camera);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
break; break;
} }
case Measure::SurfaceFeatureType::Circle: case Measure::SurfaceFeatureType::Circle:
@ -704,9 +750,17 @@ void GLGizmoMeasure::on_render()
m_curr_point_on_feature_position = center; m_curr_point_on_feature_position = center;
else { else {
const Vec3d world_pof = position_on_feature(CIRCLE_ID, camera, [](const Vec3f& v) { return v; }); const Vec3d world_pof = position_on_feature(CIRCLE_ID, camera, [](const Vec3f& v) { return v; });
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Eigen::Hyperplane<double, 3> plane(normal, center);
#else
const Eigen::Hyperplane<double, 3> plane(m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal, m_volume_matrix * center); const Eigen::Hyperplane<double, 3> plane(m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal, m_volume_matrix * center);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Transform3d local_to_model_matrix = Geometry::translation_transform(center) * Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), normal); const Transform3d local_to_model_matrix = Geometry::translation_transform(center) * Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), normal);
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Vec3d local_proj = local_to_model_matrix.inverse() * plane.projection(world_pof);
#else
const Vec3d local_proj = local_to_model_matrix.inverse() * m_volume_matrix.inverse() * plane.projection(world_pof); const Vec3d local_proj = local_to_model_matrix.inverse() * m_volume_matrix.inverse() * plane.projection(world_pof);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
double angle = std::atan2(local_proj.y(), local_proj.x()); double angle = std::atan2(local_proj.y(), local_proj.x());
if (angle < 0.0) if (angle < 0.0)
angle += 2.0 * double(M_PI); angle += 2.0 * double(M_PI);
@ -767,8 +821,12 @@ void GLGizmoMeasure::on_render()
default: { assert(false); break; } default: { assert(false); break; }
case Measure::SurfaceFeatureType::Point: case Measure::SurfaceFeatureType::Point:
{ {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Transform3d feature_matrix = Geometry::translation_transform(feature.get_point()) * Geometry::scale_transform(inv_zoom);
#else
const Vec3d position = TransformHelper::model_to_world(feature.get_point(), m_volume_matrix); const Vec3d position = TransformHelper::model_to_world(feature.get_point(), m_volume_matrix);
const Transform3d feature_matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); const Transform3d feature_matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
set_matrix_uniforms(feature_matrix); set_matrix_uniforms(feature_matrix);
set_emission_uniform(colors.front(), hover); set_emission_uniform(colors.front(), hover);
m_sphere.model.set_color(colors.front()); m_sphere.model.set_color(colors.front());
@ -785,8 +843,12 @@ void GLGizmoMeasure::on_render()
const auto& [center, radius, normal] = feature.get_circle(); const auto& [center, radius, normal] = feature.get_circle();
// render center // render center
if (update_raycasters_transform) { if (update_raycasters_transform) {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Transform3d center_matrix = Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom);
#else
const Vec3d center_world = TransformHelper::model_to_world(center, m_volume_matrix); const Vec3d center_world = TransformHelper::model_to_world(center, m_volume_matrix);
const Transform3d center_matrix = Geometry::translation_transform(center_world) * Geometry::scale_transform(inv_zoom); const Transform3d center_matrix = Geometry::translation_transform(center_world) * Geometry::scale_transform(inv_zoom);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
set_matrix_uniforms(center_matrix); set_matrix_uniforms(center_matrix);
set_emission_uniform(colors.front(), hover); set_emission_uniform(colors.front(), hover);
m_sphere.model.set_color(colors.front()); m_sphere.model.set_color(colors.front());
@ -809,7 +871,11 @@ void GLGizmoMeasure::on_render()
} }
else { else {
GLModel circle; GLModel circle;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), Transform3f::Identity());
#else
GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), m_volume_matrix.cast<float>()); GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), m_volume_matrix.cast<float>());
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
circle.init_from(std::move(circle_geometry)); circle.init_from(std::move(circle_geometry));
set_emission_uniform(colors.back(), hover); set_emission_uniform(colors.back(), hover);
circle.set_color(colors.back()); circle.set_color(colors.back());
@ -825,8 +891,12 @@ void GLGizmoMeasure::on_render()
if (update_raycasters_transform) { if (update_raycasters_transform) {
const std::optional<Vec3d> extra = feature.get_extra_point(); const std::optional<Vec3d> extra = feature.get_extra_point();
if (extra.has_value()) { if (extra.has_value()) {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Transform3d point_matrix = Geometry::translation_transform(*extra) * Geometry::scale_transform(inv_zoom);
#else
const Vec3d extra_world = TransformHelper::model_to_world(*extra, m_volume_matrix); const Vec3d extra_world = TransformHelper::model_to_world(*extra, m_volume_matrix);
const Transform3d point_matrix = Geometry::translation_transform(extra_world) * Geometry::scale_transform(inv_zoom); const Transform3d point_matrix = Geometry::translation_transform(extra_world) * Geometry::scale_transform(inv_zoom);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
set_matrix_uniforms(point_matrix); set_matrix_uniforms(point_matrix);
set_emission_uniform(colors.front(), hover); set_emission_uniform(colors.front(), hover);
m_sphere.model.set_color(colors.front()); m_sphere.model.set_color(colors.front());
@ -838,11 +908,17 @@ void GLGizmoMeasure::on_render()
} }
// render edge // render edge
if (m_mode != EMode::CenterSelection) { if (m_mode != EMode::CenterSelection) {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Transform3d edge_matrix = Geometry::translation_transform(from) *
Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), to - from) *
Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to - from).norm() });
#else
const Vec3d from_world = TransformHelper::model_to_world(from, m_volume_matrix); const Vec3d from_world = TransformHelper::model_to_world(from, m_volume_matrix);
const Vec3d to_world = TransformHelper::model_to_world(to, m_volume_matrix); const Vec3d to_world = TransformHelper::model_to_world(to, m_volume_matrix);
const Transform3d edge_matrix = Geometry::translation_transform(from_world) * const Transform3d edge_matrix = Geometry::translation_transform(from_world) *
Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), to_world - from_world) * Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), to_world - from_world) *
Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to_world - from_world).norm() }); Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to_world - from_world).norm() });
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
set_matrix_uniforms(edge_matrix); set_matrix_uniforms(edge_matrix);
set_emission_uniform(colors.back(), hover); set_emission_uniform(colors.back(), hover);
m_cylinder.model.set_color(colors.back()); m_cylinder.model.set_color(colors.back());
@ -857,16 +933,27 @@ void GLGizmoMeasure::on_render()
} }
case Measure::SurfaceFeatureType::Plane: case Measure::SurfaceFeatureType::Plane:
{ {
// no need to render the plane in case it is rendered with the same color as the volume in the 3D scene
if (colors.front() != m_parent.get_selection().get_first_volume()->render_color) {
const auto& [idx, normal, pt] = feature.get_plane(); const auto& [idx, normal, pt] = feature.get_plane();
assert(idx < m_plane_models_cache.size()); assert(idx < m_plane_models_cache.size());
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
set_matrix_uniforms(Transform3d::Identity());
#else
set_matrix_uniforms(m_volume_matrix); set_matrix_uniforms(m_volume_matrix);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
set_emission_uniform(colors.front(), hover); set_emission_uniform(colors.front(), hover);
m_plane_models_cache[idx].set_color(colors.front()); m_plane_models_cache[idx].set_color(colors.front());
m_plane_models_cache[idx].render(); m_plane_models_cache[idx].render();
}
if (update_raycasters_transform) { if (update_raycasters_transform) {
auto it = m_raycasters.find(PLANE_ID); auto it = m_raycasters.find(PLANE_ID);
if (it != m_raycasters.end() && it->second != nullptr) if (it != m_raycasters.end() && it->second != nullptr)
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
it->second->set_transform(Transform3d::Identity());
#else
it->second->set_transform(m_volume_matrix); it->second->set_transform(m_volume_matrix);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
} }
break; break;
} }
@ -921,7 +1008,11 @@ void GLGizmoMeasure::on_render()
auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(), auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(),
[](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_1_ID; }); [](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_1_ID; });
if (it != m_selection_raycasters.end()) if (it != m_selection_raycasters.end())
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
(*it)->set_transform(Geometry::translation_transform(m_selected_features.first.feature->get_point()) * Geometry::scale_transform(inv_zoom));
#else
(*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.first.feature->get_point()) * Geometry::scale_transform(inv_zoom)); (*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.first.feature->get_point()) * Geometry::scale_transform(inv_zoom));
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
} }
} }
if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) { if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) {
@ -931,14 +1022,22 @@ void GLGizmoMeasure::on_render()
auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(), auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(),
[](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_2_ID; }); [](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_2_ID; });
if (it != m_selection_raycasters.end()) if (it != m_selection_raycasters.end())
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
(*it)->set_transform(Geometry::translation_transform(m_selected_features.second.feature->get_point()) * Geometry::scale_transform(inv_zoom));
#else
(*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.second.feature->get_point()) * Geometry::scale_transform(inv_zoom)); (*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.second.feature->get_point()) * Geometry::scale_transform(inv_zoom));
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
} }
} }
if (is_hovering_on_feature && m_curr_point_on_feature_position.has_value()) { if (is_hovering_on_feature && m_curr_point_on_feature_position.has_value()) {
if (m_hover_id != POINT_ID) { if (m_hover_id != POINT_ID) {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Transform3d matrix = Geometry::translation_transform(*m_curr_point_on_feature_position) * Geometry::scale_transform(inv_zoom);
#else
const Vec3d position = TransformHelper::model_to_world(*m_curr_point_on_feature_position, m_volume_matrix); const Vec3d position = TransformHelper::model_to_world(*m_curr_point_on_feature_position, m_volume_matrix);
const Transform3d matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); const Transform3d matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
set_matrix_uniforms(matrix); set_matrix_uniforms(matrix);
const ColorRGBA color = hover_selection_color(); const ColorRGBA color = hover_selection_color();
set_emission_uniform(color, true); set_emission_uniform(color, true);
@ -951,7 +1050,9 @@ void GLGizmoMeasure::on_render()
if (old_cullface) if (old_cullface)
glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glEnable(GL_CULL_FACE));
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
} }
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
render_dimensioning(); render_dimensioning();
} }
@ -968,6 +1069,24 @@ void GLGizmoMeasure::update_if_needed()
} }
}; };
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
auto do_update = [this, update_plane_models_cache](const std::vector<VolumeCacheItem>& volumes_cache, const Selection& selection) {
TriangleMesh composite_mesh;
for (const auto& vol : volumes_cache) {
// if (selection.is_single_full_instance() && vol.volume->is_modifier())
// continue;
TriangleMesh volume_mesh = vol.volume->mesh();
volume_mesh.transform(vol.instance->get_transformation().get_matrix() * vol.volume->get_transformation().get_matrix());
composite_mesh.merge(volume_mesh);
}
m_measuring.reset(new Measure::Measuring(composite_mesh.its));
update_plane_models_cache(m_measuring->get_mesh().its);
m_raycaster.update_from(m_measuring->get_mesh());
m_volumes_cache = volumes_cache;
};
#else
auto do_update = [this, update_plane_models_cache](const ModelObject* object, const ModelVolume* volume) { auto do_update = [this, update_plane_models_cache](const ModelObject* object, const ModelVolume* volume) {
const indexed_triangle_set& its = (volume != nullptr) ? volume->mesh().its : object->volumes.front()->mesh().its; const indexed_triangle_set& its = (volume != nullptr) ? volume->mesh().its : object->volumes.front()->mesh().its;
m_measuring.reset(new Measure::Measuring(its)); m_measuring.reset(new Measure::Measuring(its));
@ -990,11 +1109,31 @@ void GLGizmoMeasure::update_if_needed()
m_old_model_object = object; m_old_model_object = object;
m_old_model_volume = volume; m_old_model_volume = volume;
}; };
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
if (selection.is_empty()) if (selection.is_empty())
return; return;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Selection::IndicesList& idxs = selection.get_volume_idxs();
std::vector<VolumeCacheItem> volumes_cache;
volumes_cache.reserve(idxs.size());
for (unsigned int idx : idxs) {
const GLVolume* v = selection.get_volume(idx);
const ModelObject* obj = selection.get_model()->objects[v->object_idx()];
const ModelInstance* inst = obj->instances[v->instance_idx()];
const ModelVolume* vol = obj->volumes[v->volume_idx()];
const VolumeCacheItem item = { obj, inst, vol, inst->get_matrix() * vol->get_matrix() };
volumes_cache.emplace_back(item);
}
if (m_state != On || volumes_cache.empty())
return;
if (m_measuring == nullptr || m_volumes_cache != volumes_cache)
do_update(volumes_cache, selection);
#else
m_volume_matrix = selection.get_first_volume()->world_matrix(); m_volume_matrix = selection.get_first_volume()->world_matrix();
const ModelObject* mo = m_c->selection_info()->model_object(); const ModelObject* mo = m_c->selection_info()->model_object();
@ -1023,6 +1162,7 @@ void GLGizmoMeasure::update_if_needed()
break; break;
} }
} }
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
} }
void GLGizmoMeasure::disable_scene_raycasters() void GLGizmoMeasure::disable_scene_raycasters()
@ -1142,6 +1282,62 @@ void GLGizmoMeasure::render_dimensioning()
const double ratio = new_value / old_value; const double ratio = new_value / old_value;
wxGetApp().plater()->take_snapshot(_L("Scale")); wxGetApp().plater()->take_snapshot(_L("Scale"));
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
struct TrafoData
{
double ratio;
Vec3d old_pivot;
Vec3d new_pivot;
Transform3d scale_matrix;
TrafoData(double ratio, const Vec3d& pivot) {
this->ratio = ratio;
this->scale_matrix = Geometry::scale_transform(ratio);
this->old_pivot = pivot;
this->new_pivot = { pivot.x(), pivot.y(), (this->scale_matrix * pivot).z() };
}
Vec3d transform(const Vec3d& point) const {
return this->scale_matrix * (point - this->old_pivot) + this->new_pivot;
}
};
auto scale_feature = [this](Measure::SurfaceFeature& feature, const TrafoData& trafo_data) {
switch (feature.get_type())
{
case Measure::SurfaceFeatureType::Point:
{
feature = Measure::SurfaceFeature(trafo_data.transform(feature.get_point()));
break;
}
case Measure::SurfaceFeatureType::Edge:
{
const auto [from, to] = feature.get_edge();
const std::optional<Vec3d> extra = feature.get_extra_point();
const std::optional<Vec3d> new_extra = extra.has_value() ? trafo_data.transform(*extra) : extra;
feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Edge, trafo_data.transform(from), trafo_data.transform(to), new_extra);
break;
}
case Measure::SurfaceFeatureType::Circle:
{
const auto [center, radius, normal] = feature.get_circle();
feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Circle, trafo_data.transform(center), normal, std::nullopt, trafo_data.ratio * radius);
break;
}
case Measure::SurfaceFeatureType::Plane:
{
const auto [idx, normal, origin] = feature.get_plane();
feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Plane, normal, trafo_data.transform(origin), std::nullopt, idx);
break;
}
}
};
const TrafoData trafo_data(ratio, m_parent.get_selection().get_bounding_box().center());
scale_feature(*m_selected_features.first.feature, trafo_data);
scale_feature(*m_selected_features.second.feature, trafo_data);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
TransformationType type; TransformationType type;
type.set_world(); type.set_world();
type.set_relative(); type.set_relative();
@ -1200,8 +1396,10 @@ void GLGizmoMeasure::render_dimensioning()
assert(f1.get_type() == Measure::SurfaceFeatureType::Point && f2.get_type() == Measure::SurfaceFeatureType::Edge); assert(f1.get_type() == Measure::SurfaceFeatureType::Point && f2.get_type() == Measure::SurfaceFeatureType::Edge);
std::pair<Vec3d, Vec3d> e = f2.get_edge(); std::pair<Vec3d, Vec3d> e = f2.get_edge();
// Transform to world coordinates // Transform to world coordinates
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
e.first = TransformHelper::model_to_world(e.first, m_volume_matrix); e.first = TransformHelper::model_to_world(e.first, m_volume_matrix);
e.second = TransformHelper::model_to_world(e.second, m_volume_matrix); e.second = TransformHelper::model_to_world(e.second, m_volume_matrix);
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Vec3d v_proj = m_measurement_result.distance_infinite->to; const Vec3d v_proj = m_measurement_result.distance_infinite->to;
@ -1482,15 +1680,21 @@ void GLGizmoMeasure::render_debug_dialog()
{ {
case Measure::SurfaceFeatureType::Point: case Measure::SurfaceFeatureType::Point:
{ {
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(item.feature->get_point()), ImGui::GetStyleColorVec4(ImGuiCol_Text));
#else
const Vec3d position = m_volume_matrix * item.feature->get_point(); const Vec3d position = m_volume_matrix * item.feature->get_point();
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text));
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
break; break;
} }
case Measure::SurfaceFeatureType::Edge: case Measure::SurfaceFeatureType::Edge:
{ {
auto [from, to] = item.feature->get_edge(); auto [from, to] = item.feature->get_edge();
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
from = m_volume_matrix * from; from = m_volume_matrix * from;
to = m_volume_matrix * to; to = m_volume_matrix * to;
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text));
break; break;
@ -1498,8 +1702,10 @@ void GLGizmoMeasure::render_debug_dialog()
case Measure::SurfaceFeatureType::Plane: case Measure::SurfaceFeatureType::Plane:
{ {
auto [idx, normal, origin] = item.feature->get_plane(); auto [idx, normal, origin] = item.feature->get_plane();
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
origin = m_volume_matrix * origin; origin = m_volume_matrix * origin;
normal = m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal; normal = m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal;
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(idx), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(idx), ImGui::GetStyleColorVec4(ImGuiCol_Text));
@ -1508,9 +1714,13 @@ void GLGizmoMeasure::render_debug_dialog()
case Measure::SurfaceFeatureType::Circle: case Measure::SurfaceFeatureType::Circle:
{ {
auto [center, radius, normal] = item.feature->get_circle(); auto [center, radius, normal] = item.feature->get_circle();
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const Vec3d on_circle = center + radius * Measure::get_orthogonal(normal, true);
#else
const Vec3d on_circle = m_volume_matrix * (center + radius * Measure::get_orthogonal(normal, true)); const Vec3d on_circle = m_volume_matrix * (center + radius * Measure::get_orthogonal(normal, true));
center = m_volume_matrix * center; center = m_volume_matrix * center;
normal = (m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal).normalized(); normal = (m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal).normalized();
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
radius = (on_circle - center).norm(); radius = (on_circle - center).norm();
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text));
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));

View File

@ -5,10 +5,16 @@
#include "slic3r/GUI/GLModel.hpp" #include "slic3r/GUI/GLModel.hpp"
#include "slic3r/GUI/GUI_Utils.hpp" #include "slic3r/GUI/GUI_Utils.hpp"
#include "libslic3r/Measure.hpp" #include "libslic3r/Measure.hpp"
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include "libslic3r/Model.hpp"
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
namespace Slic3r { namespace Slic3r {
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
class ModelVolume; class ModelVolume;
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
enum class ModelVolumeType : int; enum class ModelVolumeType : int;
@ -68,6 +74,23 @@ class GLGizmoMeasure : public GLGizmoBase
} }
}; };
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
struct VolumeCacheItem
{
const ModelObject* object{ nullptr };
const ModelInstance* instance{ nullptr };
const ModelVolume* volume{ nullptr };
Transform3d world_trafo;
bool operator == (const VolumeCacheItem& other) const {
return this->object == other.object && this->instance == other.instance && this->volume == other.volume &&
this->world_trafo.isApprox(other.world_trafo);
}
};
std::vector<VolumeCacheItem> m_volumes_cache;
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
EMode m_mode{ EMode::FeatureSelection }; EMode m_mode{ EMode::FeatureSelection };
Measure::MeasurementResult m_measurement_result; Measure::MeasurementResult m_measurement_result;
@ -85,7 +108,13 @@ class GLGizmoMeasure : public GLGizmoBase
}; };
Dimensioning m_dimensioning; Dimensioning m_dimensioning;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
// Uses a standalone raycaster and not the shared one because of the
// difference in how the mesh is updated
CommonGizmosDataObjects::Raycaster m_raycaster;
#else
Transform3d m_volume_matrix{ Transform3d::Identity() }; Transform3d m_volume_matrix{ Transform3d::Identity() };
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
std::vector<GLModel> m_plane_models_cache; std::vector<GLModel> m_plane_models_cache;
std::map<int, std::shared_ptr<SceneRaycasterItem>> m_raycasters; std::map<int, std::shared_ptr<SceneRaycasterItem>> m_raycasters;
std::vector<std::shared_ptr<SceneRaycasterItem>> m_selection_raycasters; std::vector<std::shared_ptr<SceneRaycasterItem>> m_selection_raycasters;
@ -100,17 +129,21 @@ class GLGizmoMeasure : public GLGizmoBase
std::vector<SceneRaycasterState> m_scene_raycasters; std::vector<SceneRaycasterState> m_scene_raycasters;
// These hold information to decide whether recalculation is necessary: // These hold information to decide whether recalculation is necessary:
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
std::vector<Transform3d> m_volumes_matrices; std::vector<Transform3d> m_volumes_matrices;
std::vector<ModelVolumeType> m_volumes_types; std::vector<ModelVolumeType> m_volumes_types;
Vec3d m_first_instance_scale{ Vec3d::Ones() }; Vec3d m_first_instance_scale{ Vec3d::Ones() };
Vec3d m_first_instance_mirror{ Vec3d::Ones() }; Vec3d m_first_instance_mirror{ Vec3d::Ones() };
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
float m_last_inv_zoom{ 0.0f }; float m_last_inv_zoom{ 0.0f };
std::optional<Measure::SurfaceFeature> m_last_circle; std::optional<Measure::SurfaceFeature> m_last_circle;
int m_last_plane_idx{ -1 }; int m_last_plane_idx{ -1 };
bool m_mouse_left_down{ false }; // for detection left_up of this gizmo bool m_mouse_left_down{ false }; // for detection left_up of this gizmo
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
const ModelObject* m_old_model_object{ nullptr }; const ModelObject* m_old_model_object{ nullptr };
const ModelVolume* m_old_model_volume{ nullptr }; const ModelVolume* m_old_model_volume{ nullptr };
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
Vec2d m_mouse_pos{ Vec2d::Zero() }; Vec2d m_mouse_pos{ Vec2d::Zero() };
@ -153,7 +186,9 @@ protected:
bool on_is_activable() const override; bool on_is_activable() const override;
void on_render() override; void on_render() override;
void on_set_state() override; void on_set_state() override;
#if !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
CommonGizmosDataID on_get_requirements() const override; CommonGizmosDataID on_get_requirements() const override;
#endif // !ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
virtual void on_render_input_window(float x, float y, float bottom_limit) override; virtual void on_render_input_window(float x, float y, float bottom_limit) override;
virtual void on_register_raycasters_for_picking() override; virtual void on_register_raycasters_for_picking() override;

View File

@ -327,6 +327,19 @@ const TriangleMesh* HollowedMesh::get_hollowed_interior() const
} }
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void Raycaster::update_from(const TriangleMesh& mesh)
{
std::vector<const TriangleMesh*> meshes = { &mesh };
if (meshes != m_old_meshes) {
wxBusyCursor wait;
m_raycasters.clear();
m_raycasters.emplace_back(new MeshRaycaster(std::make_shared<const TriangleMesh>(mesh)));
m_old_meshes = meshes;
}
validate();
}
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void Raycaster::on_update() void Raycaster::on_update()

View File

@ -137,6 +137,9 @@ protected:
virtual void on_update() = 0; virtual void on_update() = 0;
CommonGizmosDataPool* get_pool() const { return m_common; } CommonGizmosDataPool* get_pool() const { return m_common; }
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void validate() { m_is_valid = true; }
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
private: private:
bool m_is_valid = false; bool m_is_valid = false;
@ -242,6 +245,10 @@ public:
const MeshRaycaster* raycaster() const { assert(m_raycasters.size() == 1); return m_raycasters.front().get(); } const MeshRaycaster* raycaster() const { assert(m_raycasters.size() == 1); return m_raycasters.front().get(); }
std::vector<const MeshRaycaster*> raycasters() const; std::vector<const MeshRaycaster*> raycasters() const;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
void update_from(const TriangleMesh& mesh);
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
protected: protected:
void on_update() override; void on_update() override;
void on_release() override; void on_release() override;

View File

@ -613,6 +613,19 @@ bool Selection::contains_any_volume(const std::vector<unsigned int>& volume_idxs
return false; return false;
} }
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
bool Selection::contains_sinking_volumes(bool ignore_modifiers) const
{
for (const GLVolume* v : *m_volumes) {
if (!ignore_modifiers || !v->is_modifier) {
if (v->is_sinking())
return true;
}
}
return false;
}
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
bool Selection::matches(const std::vector<unsigned int>& volume_idxs) const bool Selection::matches(const std::vector<unsigned int>& volume_idxs) const
{ {
unsigned int count = 0; unsigned int count = 0;

View File

@ -338,6 +338,10 @@ public:
bool contains_all_volumes(const std::vector<unsigned int>& volume_idxs) const; bool contains_all_volumes(const std::vector<unsigned int>& volume_idxs) const;
// returns true if the selection contains at least one of the given indices // returns true if the selection contains at least one of the given indices
bool contains_any_volume(const std::vector<unsigned int>& volume_idxs) const; bool contains_any_volume(const std::vector<unsigned int>& volume_idxs) const;
#if ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
// returns true if the selection contains any sinking volume
bool contains_sinking_volumes(bool ignore_modifiers = true) const;
#endif // ENABLE_GIZMO_MEASURE_WORLD_COORDINATES
// returns true if the selection contains all and only the given indices // returns true if the selection contains all and only the given indices
bool matches(const std::vector<unsigned int>& volume_idxs) const; bool matches(const std::vector<unsigned int>& volume_idxs) const;