Mon, 20 Jun 2022 22:41:34 +0300
a bit of refactor in mapbox::util::nth
/* * LDForge: LDraw parts authoring CAD * Copyright (C) 2020 Teemu Piippo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <QPainter> #include <QPainterPath> #include "axesprogram.h" #include "gl/partrenderer.h" static constexpr char vertexShaderSource[] = R"( #version 330 core layout (location = 0) in vec3 in_position; layout (location = 1) in vec3 in_color; uniform mat4 mvp; smooth out vec3 ex_color; void main() { gl_Position = mvp * vec4(in_position, 1.0); ex_color = in_color; } )"; static constexpr char fragmentShaderSource[] = R"( #version 330 core out vec4 color; smooth in vec3 ex_color; void main(void) { color = vec4(ex_color, 1); } )"; void AxesLayer::initializeGL() { constexpr struct VertexType { glm::vec3 position; glm::vec3 color; } data[] = { {{10000, 0, 0}, {1, 0, 0}}, {{0, 0, 0}, {1, 0, 0}}, {{-10000, 0, 0}, {0.5, 0, 0}}, {{0, 0, 0}, {0.5, 0, 0}}, {{0, 10000, 0}, {0, 1, 0}}, {{0, 0, 0}, {0, 1, 0}}, {{0, -10000, 0}, {0, 0.5, 0}}, {{0, 0, 0}, {0, 0.5, 0}}, {{0, 0, 10000}, {0, 0, 1}}, {{0, 0, 0}, {0, 0, 1}}, {{0, 0, -10000}, {0, 0, 0.5}}, {{0, 0, 0}, {0, 0, 0.5}}, }; constexpr int stride = sizeof(VertexType); this->shader.initialize( ::vertexShaderSource, ::fragmentShaderSource, QOpenGLBuffer::StaticDraw, { GLAttributeSpec{ .type = GL_FLOAT, .offset = offsetof(VertexType, position), .tuplesize = 3, .stride = stride, }, { .type = GL_FLOAT, .offset = offsetof(VertexType, color), .tuplesize = 3, .stride = stride, }, }); 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<qreal>(fontMetrics.ascent())}; break; case RectangleSide::Left: break; case RectangleSide::Bottom: position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())}; break; case RectangleSide::Right: position += QPointF{static_cast<qreal>(-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); glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); this->shader.draw(GL_LINES); glDisable(GL_LINE_SMOOTH); } void AxesLayer::mvpMatrixChanged(const glm::mat4& mvpMatrix) { this->shader.setMvpMatrix(mvpMatrix); }