diff -r 5509bec02c81 -r 87ee9824210b src/gl/axesprogram.cpp --- a/src/gl/axesprogram.cpp Mon Jun 20 16:43:56 2022 +0300 +++ b/src/gl/axesprogram.cpp Mon Jun 20 16:59:09 2022 +0300 @@ -16,7 +16,10 @@ * along with this program. If not, see . */ +#include +#include #include "axesprogram.h" +#include "gl/partrenderer.h" static constexpr char vertexShaderSource[] = R"( #version 330 core @@ -87,6 +90,72 @@ this->shader.bufferData(&data[0], countof(data), sizeof data[0]); } +void drawBorderedText(QPainter* painter, const QPointF& point, const QFont& font, const QString& text) +{ + QPainterPath path; + path.addText(point, font, text); + painter->save(); + painter->setBrush(Qt::white); + painter->setPen({Qt::black, 0.1 * font.pointSizeF()}); + painter->drawPath(path); + painter->restore(); +} + +void AxesLayer::overpaint(QPainter* painter) +{ + QFont font; + font.setStyle(QFont::StyleItalic); + font.setBold(true); + painter->setFont(font); + QFontMetrics fontMetrics{font}; + const auto renderText = [&](const QString& text, const PointOnRectagle& intersection) + { + QPointF position = toQPointF(intersection.position); + const RectangleSide side = intersection.side; + switch (side) + { + case RectangleSide::Top: + position += QPointF{0, static_cast(fontMetrics.ascent())}; + break; + case RectangleSide::Left: + break; + case RectangleSide::Bottom: + position += QPointF{0, static_cast(-fontMetrics.descent())}; + break; + case RectangleSide::Right: + position += QPointF{static_cast(-fontMetrics.horizontalAdvance(text)), 0}; + break; + } + drawBorderedText(painter, position, font, text); + }; + const QRectF box {QPointF{0, 0}, sizeToSizeF(this->renderer->size())}; + const QPointF p1 = this->renderer->modelToScreenCoordinates(glm::vec3{0, 0, 0}); + static const struct + { + QString text; + glm::vec3 direction; + } directions[] = + { + {"+x", {1, 0, 0}}, + {"-x", {-1, 0, 0}}, + {"+y", {0, 1, 0}}, + {"-y", {0, -1, 0}}, + {"+z", {0, 0, 1}}, + {"-z", {0, 0, -1}}, + }; + for (const auto& axis : directions) + { + const QPointF x_p = this->renderer->modelToScreenCoordinates(axis.direction); + const auto intersection = rayRectangleIntersection( + rayFromPoints(toVec2(p1), toVec2(x_p)), + box); + if (intersection.has_value()) + { + renderText(axis.text, *intersection); + } + } +} + void AxesLayer::paintGL() { glLineWidth(5);