* @brief Renders the camera orientation indicator as a 2D pixmap. */
| 959 | * @brief Renders the camera orientation indicator as a 2D pixmap. |
| 960 | */ |
| 961 | QImage Widgets::Plot3D::renderCameraIndicator(const QMatrix4x4& matrix) |
| 962 | { |
| 963 | struct Axis { |
| 964 | QVector3D dir; |
| 965 | QColor color; |
| 966 | QString label; |
| 967 | }; |
| 968 | |
| 969 | struct TransformedAxis { |
| 970 | Axis axis; |
| 971 | QVector4D transformed; |
| 972 | }; |
| 973 | |
| 974 | QImage img(widgetSize(), QImage::Format_ARGB32_Premultiplied); |
| 975 | img.setDevicePixelRatio(qApp->devicePixelRatio()); |
| 976 | img.fill(Qt::transparent); |
| 977 | |
| 978 | if (width() < 240 || height() < 240) |
| 979 | return img; |
| 980 | |
| 981 | QPainter painter(&img); |
| 982 | painter.setRenderHint(QPainter::Antialiasing, true); |
| 983 | |
| 984 | const float lineScale = 18; |
| 985 | const float axisLength = 2; |
| 986 | const QPointF origin(50, 50); |
| 987 | |
| 988 | QVector<Axis> axes = { |
| 989 | {{1, 0, 0}, m_xAxisColor, QStringLiteral("X")}, |
| 990 | {{0, 1, 0}, m_yAxisColor, QStringLiteral("Y")}, |
| 991 | {{0, 0, 1}, m_zAxisColor, QStringLiteral("Z")} |
| 992 | }; |
| 993 | |
| 994 | QVector<TransformedAxis> transformedAxes; |
| 995 | for (const auto& ax : axes) { |
| 996 | QVector4D t = matrix * QVector4D(ax.dir * axisLength, 1.0f); |
| 997 | transformedAxes.append({ax, t}); |
| 998 | } |
| 999 | |
| 1000 | std::sort(transformedAxes.begin(), |
| 1001 | transformedAxes.end(), |
| 1002 | [](const TransformedAxis& a, const TransformedAxis& b) { |
| 1003 | return a.transformed.z() < b.transformed.z(); |
| 1004 | }); |
| 1005 | |
| 1006 | painter.setFont(Misc::CommonFonts::instance().customMonoFont(0.8)); |
| 1007 | QFontMetrics fm(painter.font()); |
| 1008 | int textWidth = fm.horizontalAdvance("X"); |
| 1009 | int textHeight = fm.height(); |
| 1010 | float circleRadius = std::max(textWidth, textHeight) * 0.7f; |
| 1011 | |
| 1012 | for (const auto& ta : transformedAxes) { |
| 1013 | const QVector4D& t = ta.transformed; |
| 1014 | const float invW = t.w() != 0.0f ? 1.0f / t.w() : 0.0f; |
| 1015 | QPointF endpoint(origin.x() + (t.x() * invW) * lineScale, |
| 1016 | origin.y() - (t.y() * invW) * lineScale); |
| 1017 | |
| 1018 | painter.setPen(QPen(ta.axis.color, 3)); |