src/layers/axeslayer.cpp

changeset 263
59b6027b9843
parent 259
c27612f0eac0
child 264
76a025db4948
equal deleted inserted replaced
262:dc33f8a707c4 263:59b6027b9843
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2020 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "gl/partrenderer.h"
20 #include <QPainter>
21 #include <QPainterPath>
22 #include "axeslayer.h"
23
24 static constexpr char vertexShaderSource[] = R"(
25 #version 330 core
26
27 layout (location = 0) in vec3 in_position;
28 layout (location = 1) in vec3 in_color;
29 uniform mat4 mvp;
30 smooth out vec3 ex_color;
31
32 void main()
33 {
34 gl_Position = mvp * vec4(in_position, 1.0);
35 ex_color = in_color;
36 }
37 )";
38
39 static constexpr char fragmentShaderSource[] = R"(
40 #version 330 core
41
42 out vec4 color;
43 smooth in vec3 ex_color;
44
45 void main(void)
46 {
47 color = vec4(ex_color, 1);
48 }
49 )";
50
51 void AxesLayer::initializeGL()
52 {
53 constexpr struct VertexType
54 {
55 glm::vec3 position;
56 glm::vec3 color;
57 } data[] = {
58 {{10000, 0, 0}, {1, 0, 0}},
59 {{0, 0, 0}, {1, 0, 0}},
60 {{-10000, 0, 0}, {0.5, 0, 0}},
61 {{0, 0, 0}, {0.5, 0, 0}},
62 {{0, 10000, 0}, {0, 1, 0}},
63 {{0, 0, 0}, {0, 1, 0}},
64 {{0, -10000, 0}, {0, 0.5, 0}},
65 {{0, 0, 0}, {0, 0.5, 0}},
66 {{0, 0, 10000}, {0, 0, 1}},
67 {{0, 0, 0}, {0, 0, 1}},
68 {{0, 0, -10000}, {0, 0, 0.5}},
69 {{0, 0, 0}, {0, 0, 0.5}},
70 };
71 constexpr int stride = sizeof(VertexType);
72 this->shader.initialize(
73 ::vertexShaderSource,
74 ::fragmentShaderSource,
75 QOpenGLBuffer::StaticDraw,
76 {
77 GLAttributeSpec{
78 .type = GL_FLOAT,
79 .offset = offsetof(VertexType, position),
80 .tuplesize = 3,
81 .stride = stride,
82 },
83 {
84 .type = GL_FLOAT,
85 .offset = offsetof(VertexType, color),
86 .tuplesize = 3,
87 .stride = stride,
88 },
89 });
90 this->shader.bufferData(&data[0], countof(data), sizeof data[0]);
91 }
92
93 void AxesLayer::overpaint(QPainter* painter)
94 {
95 painter->save();
96 QFont font;
97 font.setStyle(QFont::StyleItalic);
98 font.setBold(true);
99 painter->setFont(font);
100 QFontMetrics fontMetrics{font};
101 const auto renderText = [&](const QString& text, const PointOnRectagle& intersection)
102 {
103 QPointF position = toQPointF(intersection.position);
104 const RectangleSide side = intersection.side;
105 switch (side)
106 {
107 case RectangleSide::Top:
108 position += QPointF{0, static_cast<qreal>(fontMetrics.ascent())};
109 break;
110 case RectangleSide::Left:
111 break;
112 case RectangleSide::Bottom:
113 position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())};
114 break;
115 case RectangleSide::Right:
116 position += QPointF{static_cast<qreal>(-fontMetrics.horizontalAdvance(text)), 0};
117 break;
118 }
119 drawBorderedText(painter, position, font, text);
120 };
121 const QRectF box {QPointF{0, 0}, sizeToSizeF(this->renderer->size())};
122 const QPointF p1 = this->renderer->modelToScreenCoordinates(glm::vec3{0, 0, 0});
123 static const struct
124 {
125 QString text;
126 glm::vec3 direction;
127 } directions[] =
128 {
129 {"+x", {1, 0, 0}},
130 {"-x", {-1, 0, 0}},
131 {"+y", {0, 1, 0}},
132 {"-y", {0, -1, 0}},
133 {"+z", {0, 0, 1}},
134 {"-z", {0, 0, -1}},
135 };
136 for (const auto& axis : directions)
137 {
138 const QPointF x_p = this->renderer->modelToScreenCoordinates(axis.direction);
139 const auto intersection = rayRectangleIntersection(
140 rayFromPoints(toVec2(p1), toVec2(x_p)),
141 box);
142 if (intersection.has_value())
143 {
144 renderText(axis.text, *intersection);
145 }
146 }
147 painter->restore();
148 }
149
150 void AxesLayer::paintGL()
151 {
152 glLineWidth(5);
153 glEnable(GL_LINE_SMOOTH);
154 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
155 this->shader.draw(GL_LINES);
156 glDisable(GL_LINE_SMOOTH);
157 }
158
159 void AxesLayer::mvpMatrixChanged(const glm::mat4& mvpMatrix)
160 {
161 this->shader.setMvpMatrix(mvpMatrix);
162 }

mercurial