diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 249a5cce7..b36db83ad 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -2292,7 +2292,7 @@ GLModel::Geometry smooth_cylinder(unsigned int resolution, float radius, float h 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 sectorAngle = sectorStep * i; ret.emplace_back(radius * std::cos(sectorAngle), radius * std::sin(sectorAngle), 0.0f); } return ret; @@ -2351,6 +2351,51 @@ GLModel::Geometry smooth_cylinder(unsigned int resolution, float radius, float h return data; } + +GLModel::Geometry smooth_torus(unsigned int primary_resolution, unsigned int secondary_resolution, float radius, float thickness) +{ + primary_resolution = std::max(4, primary_resolution); + secondary_resolution = std::max(4, secondary_resolution); + const unsigned int torusSectorCount = primary_resolution; + const float torusSectorStep = 2.0f * float(M_PI) / float(torusSectorCount); + const unsigned int sectionSectorCount = secondary_resolution; + const float sectionSectorStep = 2.0f * float(M_PI) / float(sectionSectorCount); + + GLModel::Geometry data; + data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; + data.reserve_vertices(torusSectorCount * sectionSectorCount); + data.reserve_indices(torusSectorCount * sectionSectorCount * 2 * 3); + + // vertices + for (unsigned int i = 0; i < torusSectorCount; ++i) { + const float sectionAngle = torusSectorStep * i; + const Vec3f sectionCenter(radius * std::cos(sectionAngle), radius * std::sin(sectionAngle), 0.0f); + for (unsigned int j = 0; j < sectionSectorCount; ++j) { + const float circleAngle = sectionSectorStep * j; + const float thickness_xy = thickness * std::cos(circleAngle); + const float thickness_z = thickness * std::sin(circleAngle); + const Vec3f v(thickness_xy * std::cos(sectionAngle), thickness_xy * std::sin(sectionAngle), thickness_z); + data.add_vertex(sectionCenter + v, (Vec3f)v.normalized()); + } + } + + // triangles + for (unsigned int i = 0; i < torusSectorCount; ++i) { + const unsigned int ii = i * sectionSectorCount; + const unsigned int ii_next = ((i + 1) % torusSectorCount) * sectionSectorCount; + for (unsigned int j = 0; j < sectionSectorCount; ++j) { + const unsigned int j_next = (j + 1) % sectionSectorCount; + const unsigned int i0 = ii + j; + const unsigned int i1 = ii_next + j; + const unsigned int i2 = ii_next + j_next; + const unsigned int i3 = ii + j_next; + data.add_triangle(i0, i1, i2); + data.add_triangle(i0, i2, i3); + } + } + + return data; +} #endif // ENABLE_LEGACY_OPENGL_REMOVAL } // namespace GUI diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index c5b9f5e09..8843d39ee 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -370,6 +370,10 @@ namespace GUI { // the axis of the cylinder is the Z axis // the origin of the cylinder is the center of its bottom cap face GLModel::Geometry smooth_cylinder(unsigned int resolution, float radius, float height); + // create a torus with smooth normals + // the axis of the torus is the Z axis + // the origin of the torus is in its center + GLModel::Geometry smooth_torus(unsigned int primary_resolution, unsigned int secondary_resolution, float radius, float thickness); #endif // ENABLE_LEGACY_OPENGL_REMOVAL } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 32f110d9f..6e1ba9991 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -22,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(smooth_sphere(16, 7.5f)); - m_vbo_cylinder.init_from(smooth_cylinder(16, 5.0f, 1.0f)); + m_sphere.init_from(smooth_sphere(16, 7.5f)); + m_cylinder.init_from(smooth_cylinder(16, 5.0f, 1.0f)); } bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) @@ -188,38 +188,32 @@ void GLGizmoMeasure::on_render() 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(); + m_sphere.set_color(HOVER_COLOR); + m_sphere.render(); break; } 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(); + const Transform3d center_matrix = model_matrix * Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom); + const Transform3d center_view_model_matrix = view_matrix * center_matrix; + shader->set_uniform("view_model_matrix", center_view_model_matrix); + const Matrix3d center_view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * center_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", center_view_normal_matrix); + m_sphere.set_color(HOVER_COLOR); + m_sphere.render(); - // Now draw the circle itself - let's take a funny shortcut: - Vec3d rad = n.cross(Vec3d::UnitX()); - if (rad.squaredNorm() < 0.1) - rad = n.cross(Vec3d::UnitY()); - rad *= radius * rad.norm(); - 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(); - } + m_circle.reset(); + m_circle.init_from(smooth_torus(64, 16, float(radius), 5.0f * inv_zoom)); + + const Transform3d circle_matrix = model_matrix * Geometry::translation_transform(center); + const Transform3d circle_view_model_matrix = view_matrix * circle_matrix; + shader->set_uniform("view_model_matrix", circle_view_model_matrix); + const Matrix3d circle_view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * circle_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", circle_view_normal_matrix); + m_circle.set_color(HOVER_COLOR); + m_circle.render(); break; } case Measure::SurfaceFeatureType::Edge: @@ -232,23 +226,8 @@ void GLGizmoMeasure::on_render() 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(); - -/* - 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(); - } -*/ + m_cylinder.set_color(HOVER_COLOR); + m_cylinder.render(); break; } case Measure::SurfaceFeatureType::Plane: diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp index 72454f475..79bc934cb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp @@ -32,8 +32,9 @@ class GLGizmoMeasure : public GLGizmoBase private: std::unique_ptr m_measuring; - GLModel m_vbo_sphere; - GLModel m_vbo_cylinder; + GLModel m_sphere; + GLModel m_cylinder; + GLModel m_circle; // This holds information to decide whether recalculation is necessary: std::vector m_volumes_matrices;