| 152 } |
152 } |
| 153 |
153 |
| 154 void Canvas::paintGL() |
154 void Canvas::paintGL() |
| 155 { |
155 { |
| 156 PartRenderer::paintGL(); |
156 PartRenderer::paintGL(); |
| 157 // Render axes |
157 if (this->renderPreferences.style != gl::RenderStyle::PickScene) |
| 158 { |
158 { |
| 159 glLineWidth(5); |
159 // Render axes |
| 160 glEnable(GL_LINE_SMOOTH); |
160 { |
| 161 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
161 glLineWidth(5); |
| 162 this->axesProgram->draw(); |
162 glEnable(GL_LINE_SMOOTH); |
| 163 glDisable(GL_LINE_SMOOTH); |
163 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
| 164 } |
164 this->axesProgram->draw(); |
| 165 // Render grid |
165 glDisable(GL_LINE_SMOOTH); |
| 166 { |
166 } |
| 167 glEnable(GL_BLEND); |
167 // Render grid |
| 168 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
168 { |
| 169 this->gridProgram->draw(); |
169 glEnable(GL_BLEND); |
| 170 glDisable(GL_BLEND); |
170 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| 171 } |
171 this->gridProgram->draw(); |
| 172 if (this->worldPosition.has_value()) |
172 glDisable(GL_BLEND); |
| 173 { |
173 } |
| 174 QPainter painter{this}; |
174 if (this->worldPosition.has_value()) |
| 175 painter.setRenderHint(QPainter::Antialiasing); |
175 { |
| 176 painter.setPen(Qt::black); |
176 QPainter painter{this}; |
| 177 painter.setBrush(Qt::green); |
177 painter.setRenderHint(QPainter::Antialiasing); |
| 178 const QPointF pos = this->modelToScreenCoordinates(*this->worldPosition); |
178 painter.setPen(Qt::black); |
| 179 painter.drawEllipse(pos, 5, 5); |
179 painter.setBrush(Qt::green); |
| 180 painter.setPen(Qt::white); |
180 const QPointF pos = this->modelToScreenCoordinates(*this->worldPosition); |
| 181 painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition)); |
181 painter.drawEllipse(pos, 5, 5); |
| 182 } |
182 painter.setPen(Qt::white); |
| 183 { |
183 painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition)); |
| 184 QPainter painter{this}; |
184 } |
| 185 QFont font; |
185 { |
| 186 //font.setStyle(QFont::StyleItalic); |
186 QPainter painter{this}; |
| 187 painter.setFont(font); |
187 QFont font; |
| 188 QFontMetrics fontMetrics{font}; |
188 //font.setStyle(QFont::StyleItalic); |
| 189 const auto renderText = [&](const QString& text, const geom::PointOnRectagle& intersection) |
189 painter.setFont(font); |
| 190 { |
190 QFontMetrics fontMetrics{font}; |
| 191 QPointF position = toQPointF(intersection.position); |
191 const auto renderText = [&](const QString& text, const geom::PointOnRectagle& intersection) |
| 192 const geom::RectangleSide side = intersection.side; |
192 { |
| 193 switch (side) |
193 QPointF position = toQPointF(intersection.position); |
| 194 { |
194 const geom::RectangleSide side = intersection.side; |
| 195 case geom::RectangleSide::Top: |
195 switch (side) |
| 196 position += QPointF{0, static_cast<qreal>(fontMetrics.ascent())}; |
196 { |
| 197 break; |
197 case geom::RectangleSide::Top: |
| 198 case geom::RectangleSide::Left: |
198 position += QPointF{0, static_cast<qreal>(fontMetrics.ascent())}; |
| 199 break; |
199 break; |
| 200 case geom::RectangleSide::Bottom: |
200 case geom::RectangleSide::Left: |
| 201 position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())}; |
201 break; |
| 202 break; |
202 case geom::RectangleSide::Bottom: |
| 203 case geom::RectangleSide::Right: |
203 position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())}; |
| 204 position += QPointF{static_cast<qreal>(-fontMetrics.width(text)), 0}; |
204 break; |
| 205 break; |
205 case geom::RectangleSide::Right: |
| 206 } |
206 position += QPointF{static_cast<qreal>(-fontMetrics.width(text)), 0}; |
| 207 painter.drawText(position, text); |
207 break; |
| 208 }; |
208 } |
| 209 const QRectF box { |
209 painter.drawText(position, text); |
| 210 QPointF{0, 0}, |
210 }; |
| 211 QPointF{static_cast<qreal>(this->width()), static_cast<qreal>(this->height())} |
211 const QRectF box { |
| 212 }; |
212 QPointF{0, 0}, |
| 213 const QPointF p1 = this->modelToScreenCoordinates(glm::vec3{0, 0, 0}); |
213 QPointF{static_cast<qreal>(this->width()), static_cast<qreal>(this->height())} |
| 214 |
214 }; |
| 215 static const struct |
215 const QPointF p1 = this->modelToScreenCoordinates(glm::vec3{0, 0, 0}); |
| 216 { |
216 |
| 217 QString text; |
217 static const struct |
| 218 glm::vec3 direction; |
218 { |
| 219 } directions[] = |
219 QString text; |
| 220 { |
220 glm::vec3 direction; |
| 221 {"+𝑥", {1, 0, 0}}, |
221 } directions[] = |
| 222 {"-𝑥", {-1, 0, 0}}, |
222 { |
| 223 {"+𝑦", {0, 1, 0}}, |
223 {"+𝑥", {1, 0, 0}}, |
| 224 {"-𝑦", {0, -1, 0}}, |
224 {"-𝑥", {-1, 0, 0}}, |
| 225 {"+𝑧", {0, 0, 1}}, |
225 {"+𝑦", {0, 1, 0}}, |
| 226 {"-𝑧", {0, 0, -1}}, |
226 {"-𝑦", {0, -1, 0}}, |
| 227 }; |
227 {"+𝑧", {0, 0, 1}}, |
| 228 for (const auto& axis : directions) |
228 {"-𝑧", {0, 0, -1}}, |
| 229 { |
229 }; |
| 230 const QPointF x_p = this->modelToScreenCoordinates(axis.direction); |
230 for (const auto& axis : directions) |
| 231 const auto intersection = geom::rayRectangleIntersection(geom::rayFromPoints(toVec2(p1), toVec2(x_p)), box); |
231 { |
| 232 if (intersection.has_value()) |
232 const QPointF x_p = this->modelToScreenCoordinates(axis.direction); |
| 233 { |
233 const auto intersection = geom::rayRectangleIntersection(geom::rayFromPoints(toVec2(p1), toVec2(x_p)), box); |
| 234 renderText(axis.text, *intersection); |
234 if (intersection.has_value()) |
| |
235 { |
| |
236 renderText(axis.text, *intersection); |
| |
237 } |
| 235 } |
238 } |
| 236 } |
239 } |
| 237 } |
240 } |
| 238 } |
241 } |
| 239 |
242 |