From adb3d0101deefbdd51a3c7185ed8f768f2852efc Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 23 Aug 2022 13:17:09 +0200 Subject: [PATCH] Measuring: reworked rendering of hovered features --- src/slic3r/GUI/GLModel.cpp | 104 +++++++++++++++ src/slic3r/GUI/GLModel.hpp | 7 ++ src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 154 ++++++++++++++--------- src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp | 3 + 4 files changed, 211 insertions(+), 57 deletions(-) diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 2d6a66d43..4c98b0517 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -2253,6 +2253,110 @@ GLModel::Geometry smooth_sphere(unsigned int resolution, float radius) return data; } + +GLModel::Geometry smooth_cylinder(Axis axis, unsigned int resolution, float radius, float height) +{ + resolution = std::max(4, resolution); + + const unsigned int sectorCount = resolution; + const float sectorStep = 2.0f * float(M_PI) / float(sectorCount); + + GLModel::Geometry data; + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; + data.reserve_vertices(sectorCount * 4 + 2); + data.reserve_indices(sectorCount * 4 * 3); + + auto generate_vertices_on_circle = [sectorCount, sectorStep](Axis axis, float radius) { + std::vector ret; + ret.reserve(sectorCount); + for (unsigned int i = 0; i < sectorCount; ++i) { + // from 0 to 2pi + const float sectorAngle = (i != sectorCount) ? sectorStep * i : 0.0f; + const float x1 = radius * std::cos(sectorAngle); + const float x2 = radius * std::sin(sectorAngle); + + Vec3f v; + switch (axis) + { + case X: { v = Vec3f(0.0f, x1, x2); break; } + case Y: { v = Vec3f(-x1, 0.0f, x2); break; } + case Z: { v = Vec3f(x1, x2, 0.0f); break; } + default: { assert(false); break; } + } + + ret.emplace_back(v); + } + return ret; + }; + + const std::vector base_vertices = generate_vertices_on_circle(axis, radius); + + Vec3f h; + switch (axis) + { + case X: { h = height * Vec3f::UnitX(); break; } + case Y: { h = height * Vec3f::UnitY(); break; } + case Z: { h = height * Vec3f::UnitZ(); break; } + default: { assert(false); break; } + } + + // stem vertices + for (unsigned int i = 0; i < sectorCount; ++i) { + const Vec3f& v = base_vertices[i]; + const Vec3f n = v.normalized(); + data.add_vertex(v, n); + data.add_vertex(v + h, n); + } + + // stem triangles + for (unsigned int i = 0; i < sectorCount; ++i) { + unsigned int v1 = i * 2; + unsigned int v2 = (i < sectorCount - 1) ? v1 + 2 : 0; + unsigned int v3 = v2 + 1; + unsigned int v4 = v1 + 1; + data.add_triangle(v1, v2, v3); + data.add_triangle(v1, v3, v4); + } + + // bottom cap vertices + Vec3f cap_center = Vec3f::Zero(); + unsigned int cap_center_id = data.vertices_count(); + Vec3f normal; + switch (axis) + { + case X: { normal = -Vec3f::UnitX(); break; } + case Y: { normal = -Vec3f::UnitY(); break; } + case Z: { normal = -Vec3f::UnitZ(); break; } + default: { assert(false); break; } + } + + data.add_vertex(cap_center, normal); + for (unsigned int i = 0; i < sectorCount; ++i) { + data.add_vertex(base_vertices[i], normal); + } + + // bottom cap triangles + for (unsigned int i = 0; i < sectorCount; ++i) { + data.add_triangle(cap_center_id, (i < sectorCount - 1) ? cap_center_id + i + 2 : cap_center_id + 1, cap_center_id + i + 1); + } + + // top cap vertices + cap_center += h; + cap_center_id = data.vertices_count(); + normal = -normal; + + data.add_vertex(cap_center, normal); + for (unsigned int i = 0; i < sectorCount; ++i) { + data.add_vertex(base_vertices[i] + h, normal); + } + + // top cap triangles + for (unsigned int i = 0; i < sectorCount; ++i) { + data.add_triangle(cap_center_id, cap_center_id + i + 1, (i < sectorCount - 1) ? cap_center_id + i + 2 : cap_center_id + 1); + } + + return data; +} #endif // ENABLE_LEGACY_OPENGL_REMOVAL } // namespace GUI diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index c2845c885..393e545ab 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -376,7 +376,14 @@ namespace GUI { #if ENABLE_LEGACY_OPENGL_REMOVAL // create a sphere with the given resolution and smooth normals // the origin of the sphere is in its center + // the radius of the sphere is the given value GLModel::Geometry smooth_sphere(unsigned int resolution, float radius); + // create a cylinder with the given resolution and smooth normals + // the axis of the cylinder is the given value + // the radius of the cylinder is the given value + // the height of the cylinder is the given value + // the origin of the cylinder is in the center of the cap face having axis == 0 + GLModel::Geometry smooth_cylinder(Axis axis, unsigned int resolution, float radius, float height); #endif // ENABLE_LEGACY_OPENGL_REMOVAL } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 3e37fad74..5b6baa015 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -8,6 +8,7 @@ #include "libslic3r/Model.hpp" #include "libslic3r/Measure.hpp" +#include "libslic3r/PresetBundle.hpp" #include @@ -21,8 +22,8 @@ static const Slic3r::ColorRGBA HOVER_COLOR = { 0.8f, 0.2f, 0.2f, 1.0f }; GLGizmoMeasure::GLGizmoMeasure(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) { - m_vbo_sphere.init_from(its_make_sphere(1., M_PI/32.)); - m_vbo_cylinder.init_from(its_make_cylinder(1., 1.)); + m_vbo_sphere.init_from(smooth_sphere(16, 7.5f)); + m_vbo_cylinder.init_from(smooth_cylinder(Z, 16, 5.0f, 1.0f)); } bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) @@ -106,7 +107,9 @@ std::string GLGizmoMeasure::on_get_name() const bool GLGizmoMeasure::on_is_activable() const { const Selection& selection = m_parent.get_selection(); - return selection.is_single_volume() || selection.is_single_volume_instance(); + return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) ? + selection.is_single_full_instance() : + selection.is_single_volume() || selection.is_single_volume_instance(); } void GLGizmoMeasure::on_render() @@ -117,30 +120,27 @@ void GLGizmoMeasure::on_render() const Selection& selection = m_parent.get_selection(); - GLShaderProgram* shader = wxGetApp().get_shader("flat"); + GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; shader->start_using(); + shader->set_uniform("emission_factor", 0.25f); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_BLEND)); -#if ENABLE_GL_CORE_PROFILE - if (!OpenGLManager::get_gl_info().is_core_profile()) -#endif // ENABLE_GL_CORE_PROFILE - glsafe(::glLineWidth(2.f)); - if (selection.is_single_volume() || selection.is_single_volume_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())) { const Transform3d& model_matrix = selection.get_first_volume()->world_matrix(); const Camera& camera = wxGetApp().plater()->get_camera(); - const Transform3d view_model_matrix = camera.get_view_matrix() * - Geometry::assemble_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * model_matrix; + const Transform3d& view_matrix = camera.get_view_matrix(); + const float inv_zoom = camera.get_inv_zoom(); - shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - + update_if_needed(); Vec3f pos; @@ -148,7 +148,6 @@ void GLGizmoMeasure::on_render() size_t facet_idx; m_c->raycaster()->raycasters().front()->unproject_on_mesh(Vec2d(m_mouse_pos_x, m_mouse_pos_y), model_matrix, camera, pos, normal, nullptr, &facet_idx); -#define ENABLE_DEBUG_DIALOG 0 #if ENABLE_DEBUG_DIALOG m_imgui->begin(std::string("DEBUG")); m_imgui->checkbox(wxString("Show all features"), m_show_all); @@ -162,34 +161,46 @@ void GLGizmoMeasure::on_render() #endif // ENABLE_DEBUG_DIALOG std::vector features; - if (m_show_all) { +#if ENABLE_DEBUG_DIALOG + if (m_show_all) { features = m_measuring->get_all_features(); // EXPENSIVE - debugging only. features.erase(std::remove_if(features.begin(), features.end(), [](const Measure::SurfaceFeature& f) { return f.get_type() == Measure::SurfaceFeatureType::Plane; }), features.end()); - } else { + } + else { +#endif // ENABLE_DEBUG_DIALOG std::optional feat = m_measuring->get_feature(facet_idx, pos.cast()); - if (feat) + if (feat.has_value()) features.emplace_back(*feat); - } - - +#if ENABLE_DEBUG_DIALOG + } +#endif // ENABLE_DEBUG_DIALOG for (const Measure::SurfaceFeature& feature : features) { - - if (feature.get_type() == Measure::SurfaceFeatureType::Point) { - Transform3d view_feature_matrix = view_model_matrix * Transform3d(Eigen::Translation3d(feature.get_point())); - view_feature_matrix.scale(0.5); - shader->set_uniform("view_model_matrix", view_feature_matrix); + switch (feature.get_type()) { + case Measure::SurfaceFeatureType::Point: + { + const Vec3d& position = feature.get_point(); + const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); + const Transform3d view_model_matrix = view_matrix * feature_matrix; + shader->set_uniform("view_model_matrix", view_model_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * feature_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); m_vbo_sphere.set_color(HOVER_COLOR); m_vbo_sphere.render(); + break; } - else if (feature.get_type() == Measure::SurfaceFeatureType::Circle) { - const auto& [c, radius, n] = feature.get_circle(); - Transform3d view_feature_matrix = view_model_matrix * Transform3d(Eigen::Translation3d(c)); - view_feature_matrix.scale(0.5); - shader->set_uniform("view_model_matrix", view_feature_matrix); + case Measure::SurfaceFeatureType::Circle: + { + const auto& [center, radius, n] = feature.get_circle(); + // render center + const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom); + const Transform3d view_model_matrix = view_matrix * feature_matrix; + shader->set_uniform("view_model_matrix", view_model_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * feature_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); m_vbo_sphere.set_color(HOVER_COLOR); m_vbo_sphere.render(); @@ -198,45 +209,69 @@ void GLGizmoMeasure::on_render() if (rad.squaredNorm() < 0.1) rad = n.cross(Vec3d::UnitY()); rad *= radius * rad.norm(); - const int N = 20; - for (int i=0; iset_uniform("view_model_matrix", view_feature_matrix); + const int N = 32; + m_vbo_sphere.set_color(HOVER_COLOR); + for (int i = 0; i < N; ++i) { + rad = Eigen::AngleAxisd(2.0 * M_PI / N, n) * rad; + const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(center + rad) * Geometry::scale_transform(N / 100.0 * inv_zoom); + const Transform3d view_model_matrix = view_matrix * feature_matrix; + shader->set_uniform("view_model_matrix", view_model_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * feature_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); m_vbo_sphere.render(); } + break; } - else if (feature.get_type() == Measure::SurfaceFeatureType::Edge) { + case Measure::SurfaceFeatureType::Edge: + { const auto& [start, end] = feature.get_edge(); - Transform3d view_feature_matrix = view_model_matrix * Transform3d(Eigen::Translation3d(start)); - auto q = Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), end - start); - view_feature_matrix *= q; - view_feature_matrix.scale(Vec3d(0.075, 0.075, (end - start).norm())); - shader->set_uniform("view_model_matrix", view_feature_matrix); + auto q = Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), end - start); + const Transform3d feature_matrix = model_matrix * Geometry::translation_transform(start) * q * + Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (end - start).norm() }); + const Transform3d view_model_matrix = view_matrix * feature_matrix; + shader->set_uniform("view_model_matrix", view_model_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * feature_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); m_vbo_cylinder.set_color(HOVER_COLOR); m_vbo_cylinder.render(); - if (feature.get_extra_point()) { - Vec3d pin = *feature.get_extra_point(); - view_feature_matrix = view_model_matrix * Transform3d(Eigen::Translation3d(pin)); - view_feature_matrix.scale(0.5); - shader->set_uniform("view_model_matrix", view_feature_matrix); + +/* + std::optional extra_point = feature.get_extra_point(); + if (extra_point.has_value()) { + const Vec3d pin = *extra_point; + const Transform3d feature_matrix = Geometry::translation_transform(pin + selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * + Geometry::scale_transform(inv_zoom) * model_matrix; + const Transform3d view_model_matrix = view_matrix * feature_matrix; + shader->set_uniform("view_model_matrix", view_model_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * feature_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); m_vbo_sphere.set_color(HOVER_COLOR); m_vbo_sphere.render(); } +*/ + break; } - else if (feature.get_type() == Measure::SurfaceFeatureType::Plane) { + case Measure::SurfaceFeatureType::Plane: + { const auto& [idx, normal, pt] = feature.get_plane(); assert(idx < m_plane_models.size()); + const Transform3d view_model_matrix = view_matrix * model_matrix; + shader->set_uniform("view_model_matrix", view_model_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); m_plane_models[idx]->set_color(HOVER_COLOR); m_plane_models[idx]->render(); - } + break; + } + } } - shader->set_uniform("view_model_matrix", view_model_matrix); +#if ENABLE_DEBUG_DIALOG if (m_show_planes) - for (const auto& glmodel : m_plane_models) + for (const auto& glmodel : m_plane_models) { + glmodel->set_color(HOVER_COLOR); glmodel->render(); + } +#endif // ENABLE_DEBUG_DIALOG } glsafe(::glEnable(GL_CULL_FACE)); @@ -272,14 +307,19 @@ void GLGizmoMeasure::update_if_needed() const std::vector> planes_triangles = m_measuring->get_planes_triangle_indices(); for (const std::vector& triangle_indices : planes_triangles) { m_plane_models.emplace_back(std::unique_ptr(new GLModel())); - GUI::GLModel::Geometry init_data; - init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3 }; + GLModel::Geometry init_data; + init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; init_data.color = ColorRGBA(0.9f, 0.9f, 0.9f, 0.5f); int i = 0; for (int idx : triangle_indices) { - init_data.add_vertex(its.vertices[its.indices[idx][0]]); - init_data.add_vertex(its.vertices[its.indices[idx][1]]); - init_data.add_vertex(its.vertices[its.indices[idx][2]]); + const Vec3f& v0 = its.vertices[its.indices[idx][0]]; + const Vec3f& v1 = its.vertices[its.indices[idx][1]]; + const Vec3f& v2 = its.vertices[its.indices[idx][2]]; + + const Vec3f n = (v1 - v0).cross(v2 - v0).normalized(); + init_data.add_vertex(v0, n); + init_data.add_vertex(v1, n); + init_data.add_vertex(v2, n); init_data.add_triangle(i, i + 1, i + 2); i += 3; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp index 68baffd4c..823171171 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp @@ -11,6 +11,7 @@ #include +#define ENABLE_DEBUG_DIALOG 0 namespace Slic3r { @@ -48,8 +49,10 @@ private: int m_mouse_pos_x; int m_mouse_pos_y; +#if ENABLE_DEBUG_DIALOG bool m_show_all = false; bool m_show_planes = false; +#endif // ENABLE_DEBUG_DIALOG std::vector> m_plane_models; void update_if_needed();