159 painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition)); |
160 painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition)); |
160 } |
161 } |
161 { |
162 { |
162 QPainter painter{this}; |
163 QPainter painter{this}; |
163 painter.setRenderHint(QPainter::Antialiasing); |
164 painter.setRenderHint(QPainter::Antialiasing); |
164 QFont font; |
165 if (this->renderPreferences.drawAxes) |
165 //font.setStyle(QFont::StyleItalic); |
|
166 painter.setFont(font); |
|
167 QFontMetrics fontMetrics{font}; |
|
168 const auto renderText = [&](const QString& text, const geom::PointOnRectagle& intersection) |
|
169 { |
166 { |
170 QPointF position = toQPointF(intersection.position); |
167 this->renderAxesLabels(painter); |
171 const geom::RectangleSide side = intersection.side; |
|
172 switch (side) |
|
173 { |
|
174 case geom::RectangleSide::Top: |
|
175 position += QPointF{0, static_cast<qreal>(fontMetrics.ascent())}; |
|
176 break; |
|
177 case geom::RectangleSide::Left: |
|
178 break; |
|
179 case geom::RectangleSide::Bottom: |
|
180 position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())}; |
|
181 break; |
|
182 case geom::RectangleSide::Right: |
|
183 position += QPointF{static_cast<qreal>(-fontMetrics.horizontalAdvance(text)), 0}; |
|
184 break; |
|
185 } |
|
186 painter.drawText(position, text); |
|
187 }; |
|
188 const QRectF box {QPointF{0, 0}, sizeToSizeF(this->size())}; |
|
189 const QPointF p1 = this->modelToScreenCoordinates(glm::vec3{0, 0, 0}); |
|
190 |
|
191 static const struct |
|
192 { |
|
193 QString text; |
|
194 glm::vec3 direction; |
|
195 } directions[] = |
|
196 { |
|
197 {"+𝑥", {1, 0, 0}}, |
|
198 {"-𝑥", {-1, 0, 0}}, |
|
199 {"+𝑦", {0, 1, 0}}, |
|
200 {"-𝑦", {0, -1, 0}}, |
|
201 {"+𝑧", {0, 0, 1}}, |
|
202 {"-𝑧", {0, 0, -1}}, |
|
203 }; |
|
204 for (const auto& axis : directions) |
|
205 { |
|
206 const QPointF x_p = this->modelToScreenCoordinates(axis.direction); |
|
207 const auto intersection = geom::rayRectangleIntersection( |
|
208 geom::rayFromPoints(toVec2(p1), toVec2(x_p)), |
|
209 box); |
|
210 if (intersection.has_value()) |
|
211 { |
|
212 renderText(axis.text, *intersection); |
|
213 } |
|
214 } |
168 } |
215 if (this->overpaintCallback != nullptr) |
169 if (this->overpaintCallback != nullptr) |
216 { |
170 { |
217 this->overpaintCallback(this, &painter); |
171 this->overpaintCallback(this, &painter); |
218 } |
172 } |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 /** |
|
178 * @brief Renders labels such as +x at the ends of axes at the screen |
|
179 * @param painter |
|
180 */ |
|
181 void Canvas::renderAxesLabels(QPainter& painter) |
|
182 { |
|
183 QFont font; |
|
184 //font.setStyle(QFont::StyleItalic); |
|
185 painter.setFont(font); |
|
186 QFontMetrics fontMetrics{font}; |
|
187 const auto renderText = [&](const QString& text, const geom::PointOnRectagle& intersection) |
|
188 { |
|
189 QPointF position = toQPointF(intersection.position); |
|
190 const geom::RectangleSide side = intersection.side; |
|
191 switch (side) |
|
192 { |
|
193 case geom::RectangleSide::Top: |
|
194 position += QPointF{0, static_cast<qreal>(fontMetrics.ascent())}; |
|
195 break; |
|
196 case geom::RectangleSide::Left: |
|
197 break; |
|
198 case geom::RectangleSide::Bottom: |
|
199 position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())}; |
|
200 break; |
|
201 case geom::RectangleSide::Right: |
|
202 position += QPointF{static_cast<qreal>(-fontMetrics.horizontalAdvance(text)), 0}; |
|
203 break; |
|
204 } |
|
205 painter.drawText(position, text); |
|
206 }; |
|
207 const QRectF box {QPointF{0, 0}, sizeToSizeF(this->size())}; |
|
208 const QPointF p1 = this->modelToScreenCoordinates(glm::vec3{0, 0, 0}); |
|
209 static const struct |
|
210 { |
|
211 QString text; |
|
212 glm::vec3 direction; |
|
213 } directions[] = |
|
214 { |
|
215 {"+𝑥", {1, 0, 0}}, |
|
216 {"-𝑥", {-1, 0, 0}}, |
|
217 {"+𝑦", {0, 1, 0}}, |
|
218 {"-𝑦", {0, -1, 0}}, |
|
219 {"+𝑧", {0, 0, 1}}, |
|
220 {"-𝑧", {0, 0, -1}}, |
|
221 }; |
|
222 for (const auto& axis : directions) |
|
223 { |
|
224 const QPointF x_p = this->modelToScreenCoordinates(axis.direction); |
|
225 const auto intersection = geom::rayRectangleIntersection( |
|
226 geom::rayFromPoints(toVec2(p1), toVec2(x_p)), |
|
227 box); |
|
228 if (intersection.has_value()) |
|
229 { |
|
230 renderText(axis.text, *intersection); |
219 } |
231 } |
220 } |
232 } |
221 } |
233 } |
222 |
234 |
223 /** |
235 /** |