src/gl/partrenderer.cpp

changeset 58
b7841cd31fb7
parent 57
5c0005f63319
child 59
60650929dc82
equal deleted inserted replaced
57:5c0005f63319 58:b7841cd31fb7
284 glm::vec3 PartRenderer::viewport(const glm::vec3& point) 284 glm::vec3 PartRenderer::viewport(const glm::vec3& point)
285 { 285 {
286 return viewport(point, this->width(), this->height()); 286 return viewport(point, this->width(), this->height());
287 } 287 }
288 288
289 std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point) 289 /**
290 * @brief Converts the specified on the screen into the 3D world. The point is unprojected twice into 3D and the
291 * intersection of the resulting line with the specified plane is returned. If the intersection point lies behind
292 * the camera, no value is returned.
293 * @param point 2D window co-ordinates to convert.
294 * @param plane Plane to raycast against
295 * @return world co-ordinates, or no value if the point is behind the camera.
296 */
297 std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane)
290 { 298 {
291 auto p1 = this->unproject({point.x(), point.y(), 0}); 299 auto p1 = this->unproject({point.x(), point.y(), 0});
292 auto p2 = this->unproject({point.x(), point.y(), 1}); 300 auto p2 = this->unproject({point.x(), point.y(), 1});
293 geom::Line line = geom::lineFromPoints(p1, p2); 301 geom::Line line = geom::lineFromPoints(p1, p2);
294 return geom::linePlaneIntersection(line, geom::XY); 302 std::optional<glm::vec3> result;
295 } 303 // If the dot product between the line direction and plane normal is negative, the point
296 304 // of intersection lies behind the camera.
305 if (glm::dot(line.direction, plane.normal) > 0)
306 {
307 result = geom::linePlaneIntersection(line, plane, 0.01);
308 }
309 return result;
310 }
311
312 /**
313 * @brief Converts the specified point to 2D window coordinates, with Y-coordinate inverted for Qt
314 * @param point Point to unproject
315 * @return screen coordinates
316 */
297 QPointF PartRenderer::modelToScreenCoordinates(const glm::vec3& point) 317 QPointF PartRenderer::modelToScreenCoordinates(const glm::vec3& point)
298 { 318 {
299 glm::vec4 p = {point, 1}; 319 const glm::vec3 projected = glm::project(
300 p = glm::mat4_cast(this->modelQuaternion) * p; 320 point,
301 p = this->viewMatrix * p; 321 this->viewMatrix * glm::mat4_cast(this->modelQuaternion),
302 p = this->projectionMatrix * p; 322 this->projectionMatrix,
303 glm::vec2 pp = this->viewport({p.x / p.w, p.y / p.w, 1}); 323 this->viewportVector);
304 return toQPointF(pp); 324 return {projected.x, this->height() - projected.y};
305 } 325 }
306 326
327 /**
328 * @brief Unprojects the specified window coordinates to model coordinates
329 * @param win Window coordinates to project. Z-coordinate indicates depth
330 * @return model coordinates
331 */
307 glm::vec3 PartRenderer::unproject(const glm::vec3& win) 332 glm::vec3 PartRenderer::unproject(const glm::vec3& win)
308 { 333 {
309 return glm::unProject( 334 return glm::unProject(
310 glm::vec3{win.x, this->height() - win.y, win.z}, 335 glm::vec3{win.x, this->height() - win.y, win.z},
311 this->viewMatrix * glm::mat4_cast(this->modelQuaternion), 336 this->viewMatrix * glm::mat4_cast(this->modelQuaternion),

mercurial