src/gl/partrenderer.cpp

changeset 58
b7841cd31fb7
parent 57
5c0005f63319
child 59
60650929dc82
--- a/src/gl/partrenderer.cpp	Thu Feb 27 11:56:41 2020 +0200
+++ b/src/gl/partrenderer.cpp	Thu Feb 27 12:23:42 2020 +0200
@@ -286,24 +286,49 @@
 	return viewport(point, this->width(), this->height());
 }
 
-std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point)
+/**
+ * @brief Converts the specified on the screen into the 3D world. The point is unprojected twice into 3D and the
+ * intersection of the resulting line with the specified plane is returned. If the intersection point lies behind
+ * the camera, no value is returned.
+ * @param point 2D window co-ordinates to convert.
+ * @param plane Plane to raycast against
+ * @return world co-ordinates, or no value if the point is behind the camera.
+ */
+std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane)
 {
 	auto p1 = this->unproject({point.x(), point.y(), 0});
 	auto p2 = this->unproject({point.x(), point.y(), 1});
 	geom::Line line = geom::lineFromPoints(p1, p2);
-	return geom::linePlaneIntersection(line, geom::XY);
+	std::optional<glm::vec3> result;
+	// If the dot product between the line direction and plane normal is negative, the point
+	// of intersection lies behind the camera.
+	if (glm::dot(line.direction, plane.normal) > 0)
+	{
+		result = geom::linePlaneIntersection(line, plane, 0.01);
+	}
+	return result;
 }
 
+/**
+ * @brief Converts the specified point to 2D window coordinates, with Y-coordinate inverted for Qt
+ * @param point Point to unproject
+ * @return screen coordinates
+ */
 QPointF PartRenderer::modelToScreenCoordinates(const glm::vec3& point)
 {
-	glm::vec4 p = {point, 1};
-	p = glm::mat4_cast(this->modelQuaternion) * p;
-	p = this->viewMatrix * p;
-	p = this->projectionMatrix * p;
-	glm::vec2 pp = this->viewport({p.x / p.w, p.y / p.w, 1});
-	return toQPointF(pp);
+	const glm::vec3 projected = glm::project(
+		point,
+		this->viewMatrix * glm::mat4_cast(this->modelQuaternion),
+		this->projectionMatrix,
+		this->viewportVector);
+	return {projected.x, this->height() - projected.y};
 }
 
+/**
+ * @brief Unprojects the specified window coordinates to model coordinates
+ * @param win Window coordinates to project. Z-coordinate indicates depth
+ * @return model coordinates
+ */
 glm::vec3 PartRenderer::unproject(const glm::vec3& win)
 {
 	return glm::unProject(

mercurial