14 * |
14 * |
15 * You should have received a copy of the GNU General Public License |
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/>. |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 */ |
17 */ |
18 |
18 |
|
19 #include <QPainter> |
|
20 #include <QPainterPath> |
19 #include "axesprogram.h" |
21 #include "axesprogram.h" |
|
22 #include "gl/partrenderer.h" |
20 |
23 |
21 static constexpr char vertexShaderSource[] = R"( |
24 static constexpr char vertexShaderSource[] = R"( |
22 #version 330 core |
25 #version 330 core |
23 |
26 |
24 layout (location = 0) in vec3 in_position; |
27 layout (location = 0) in vec3 in_position; |
85 }, |
88 }, |
86 }); |
89 }); |
87 this->shader.bufferData(&data[0], countof(data), sizeof data[0]); |
90 this->shader.bufferData(&data[0], countof(data), sizeof data[0]); |
88 } |
91 } |
89 |
92 |
|
93 void drawBorderedText(QPainter* painter, const QPointF& point, const QFont& font, const QString& text) |
|
94 { |
|
95 QPainterPath path; |
|
96 path.addText(point, font, text); |
|
97 painter->save(); |
|
98 painter->setBrush(Qt::white); |
|
99 painter->setPen({Qt::black, 0.1 * font.pointSizeF()}); |
|
100 painter->drawPath(path); |
|
101 painter->restore(); |
|
102 } |
|
103 |
|
104 void AxesLayer::overpaint(QPainter* painter) |
|
105 { |
|
106 QFont font; |
|
107 font.setStyle(QFont::StyleItalic); |
|
108 font.setBold(true); |
|
109 painter->setFont(font); |
|
110 QFontMetrics fontMetrics{font}; |
|
111 const auto renderText = [&](const QString& text, const PointOnRectagle& intersection) |
|
112 { |
|
113 QPointF position = toQPointF(intersection.position); |
|
114 const RectangleSide side = intersection.side; |
|
115 switch (side) |
|
116 { |
|
117 case RectangleSide::Top: |
|
118 position += QPointF{0, static_cast<qreal>(fontMetrics.ascent())}; |
|
119 break; |
|
120 case RectangleSide::Left: |
|
121 break; |
|
122 case RectangleSide::Bottom: |
|
123 position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())}; |
|
124 break; |
|
125 case RectangleSide::Right: |
|
126 position += QPointF{static_cast<qreal>(-fontMetrics.horizontalAdvance(text)), 0}; |
|
127 break; |
|
128 } |
|
129 drawBorderedText(painter, position, font, text); |
|
130 }; |
|
131 const QRectF box {QPointF{0, 0}, sizeToSizeF(this->renderer->size())}; |
|
132 const QPointF p1 = this->renderer->modelToScreenCoordinates(glm::vec3{0, 0, 0}); |
|
133 static const struct |
|
134 { |
|
135 QString text; |
|
136 glm::vec3 direction; |
|
137 } directions[] = |
|
138 { |
|
139 {"+x", {1, 0, 0}}, |
|
140 {"-x", {-1, 0, 0}}, |
|
141 {"+y", {0, 1, 0}}, |
|
142 {"-y", {0, -1, 0}}, |
|
143 {"+z", {0, 0, 1}}, |
|
144 {"-z", {0, 0, -1}}, |
|
145 }; |
|
146 for (const auto& axis : directions) |
|
147 { |
|
148 const QPointF x_p = this->renderer->modelToScreenCoordinates(axis.direction); |
|
149 const auto intersection = rayRectangleIntersection( |
|
150 rayFromPoints(toVec2(p1), toVec2(x_p)), |
|
151 box); |
|
152 if (intersection.has_value()) |
|
153 { |
|
154 renderText(axis.text, *intersection); |
|
155 } |
|
156 } |
|
157 } |
|
158 |
90 void AxesLayer::paintGL() |
159 void AxesLayer::paintGL() |
91 { |
160 { |
92 glLineWidth(5); |
161 glLineWidth(5); |
93 glEnable(GL_LINE_SMOOTH); |
162 glEnable(GL_LINE_SMOOTH); |
94 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
163 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |