279 * the camera, no value is returned. |
279 * the camera, no value is returned. |
280 * @param point 2D window co-ordinates to convert. |
280 * @param point 2D window co-ordinates to convert. |
281 * @param plane Plane to raycast against |
281 * @param plane Plane to raycast against |
282 * @return world co-ordinates, or no value if the point is behind the camera. |
282 * @return world co-ordinates, or no value if the point is behind the camera. |
283 */ |
283 */ |
284 std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane) |
284 std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane) const |
285 { |
285 { |
286 const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0}); |
286 const geom::Line line = this->cameraLine(point); |
287 const glm::vec3 p2 = this->unproject({point.x(), point.y(), 1}); |
|
288 const geom::Line line = geom::lineFromPoints(p1, p2); |
|
289 std::optional<glm::vec3> result; |
287 std::optional<glm::vec3> result; |
290 result = geom::linePlaneIntersection(line, plane, 0.01f); |
288 result = geom::linePlaneIntersection(line, plane, 0.01f); |
291 // If the point lies behind the camera, do not return a result. |
289 // If the point lies behind the camera, do not return a result. |
292 if (result.has_value() and glm::dot(line.direction, *result - p1) < 0) |
290 if (result.has_value() and glm::dot(line.direction, *result - line.anchor) < 0) |
293 { |
291 { |
294 result.reset(); |
292 result.reset(); |
295 } |
293 } |
296 return result; |
294 return result; |
297 } |
295 } |
299 /** |
297 /** |
300 * @brief Converts the specified point to 2D window coordinates, with Y-coordinate inverted for Qt |
298 * @brief Converts the specified point to 2D window coordinates, with Y-coordinate inverted for Qt |
301 * @param point Point to unproject |
299 * @param point Point to unproject |
302 * @return screen coordinates |
300 * @return screen coordinates |
303 */ |
301 */ |
304 QPointF PartRenderer::modelToScreenCoordinates(const glm::vec3& point) |
302 QPointF PartRenderer::modelToScreenCoordinates(const glm::vec3& point) const |
305 { |
303 { |
306 const glm::vec3 projected = glm::project( |
304 const glm::vec3 projected = glm::project( |
307 point, |
305 point, |
308 this->viewMatrix * glm::mat4_cast(this->modelQuaternion), |
306 this->viewMatrix * glm::mat4_cast(this->modelQuaternion), |
309 this->projectionMatrix, |
307 this->projectionMatrix, |
310 this->viewportVector); |
308 this->viewportVector); |
311 return toQPointF(glm::vec2{projected.x, this->height() - projected.y}); |
309 return toQPointF(glm::vec2{projected.x, this->height() - projected.y}); |
312 } |
310 } |
313 |
311 |
|
312 geom::Line PartRenderer::cameraLine(const QPoint& point) const |
|
313 { |
|
314 const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0}); |
|
315 const glm::vec3 p2 = this->unproject({point.x(), point.y(), 1}); |
|
316 return geom::lineFromPoints(p1, p2); |
|
317 } |
|
318 |
314 /** |
319 /** |
315 * @brief Unprojects the specified window coordinates to model coordinates |
320 * @brief Unprojects the specified window coordinates to model coordinates |
316 * @param win Window coordinates to project. Z-coordinate indicates depth |
321 * @param win Window coordinates to project. Z-coordinate indicates depth |
317 * @return model coordinates |
322 * @return model coordinates |
318 */ |
323 */ |
319 glm::vec3 PartRenderer::unproject(const glm::vec3& win) |
324 glm::vec3 PartRenderer::unproject(const glm::vec3& win) const |
320 { |
325 { |
321 return glm::unProject( |
326 return glm::unProject( |
322 glm::vec3{win.x, this->height() - win.y, win.z}, |
327 glm::vec3{win.x, this->height() - win.y, win.z}, |
323 this->viewMatrix * glm::mat4_cast(this->modelQuaternion), |
328 this->viewMatrix * glm::mat4_cast(this->modelQuaternion), |
324 this->projectionMatrix, |
329 this->projectionMatrix, |