Mon, 02 Mar 2020 11:08:13 +0200
added a method to find out if the view is perpendicular to grid
src/gl/partrenderer.cpp | file | annotate | diff | comparison | revisions | |
src/gl/partrenderer.h | file | annotate | diff | comparison | revisions | |
src/ui/canvas.cpp | file | annotate | diff | comparison | revisions | |
src/ui/canvas.h | file | annotate | diff | comparison | revisions |
--- a/src/gl/partrenderer.cpp Sat Feb 29 23:51:03 2020 +0200 +++ b/src/gl/partrenderer.cpp Mon Mar 02 11:08:13 2020 +0200 @@ -281,15 +281,13 @@ * @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) +std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane) const { - const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0}); - const glm::vec3 p2 = this->unproject({point.x(), point.y(), 1}); - const geom::Line line = geom::lineFromPoints(p1, p2); + const geom::Line line = this->cameraLine(point); std::optional<glm::vec3> result; result = geom::linePlaneIntersection(line, plane, 0.01f); // If the point lies behind the camera, do not return a result. - if (result.has_value() and glm::dot(line.direction, *result - p1) < 0) + if (result.has_value() and glm::dot(line.direction, *result - line.anchor) < 0) { result.reset(); } @@ -301,7 +299,7 @@ * @param point Point to unproject * @return screen coordinates */ -QPointF PartRenderer::modelToScreenCoordinates(const glm::vec3& point) +QPointF PartRenderer::modelToScreenCoordinates(const glm::vec3& point) const { const glm::vec3 projected = glm::project( point, @@ -311,12 +309,19 @@ return toQPointF(glm::vec2{projected.x, this->height() - projected.y}); } +geom::Line PartRenderer::cameraLine(const QPoint& point) const +{ + const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0}); + const glm::vec3 p2 = this->unproject({point.x(), point.y(), 1}); + return geom::lineFromPoints(p1, p2); +} + /** * @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) +glm::vec3 PartRenderer::unproject(const glm::vec3& win) const { return glm::unProject( glm::vec3{win.x, this->height() - win.y, win.z},
--- a/src/gl/partrenderer.h Sat Feb 29 23:51:03 2020 +0200 +++ b/src/gl/partrenderer.h Mon Mar 02 11:08:13 2020 +0200 @@ -34,9 +34,10 @@ const ldraw::ColorTable& colorTable; gl::Compiler* const compiler; ldraw::Id highlighted = ldraw::NULL_ID; - std::optional<glm::vec3> screenToModelCoordinates(const QPoint& point, const geom::Plane& plane); - QPointF modelToScreenCoordinates(const glm::vec3& point); - glm::vec3 unproject(const glm::vec3& win); + std::optional<glm::vec3> screenToModelCoordinates(const QPoint& point, const geom::Plane& plane) const; + QPointF modelToScreenCoordinates(const glm::vec3& point) const; + geom::Line cameraLine(const QPoint& point) const; + glm::vec3 unproject(const glm::vec3& win) const; glm::mat4 projectionMatrix; glm::mat4 viewMatrix; glm::mat4 modelMatrix;
--- a/src/ui/canvas.cpp Sat Feb 29 23:51:03 2020 +0200 +++ b/src/ui/canvas.cpp Mon Mar 02 11:08:13 2020 +0200 @@ -45,6 +45,7 @@ // grid matrix. this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1}; } + /* if (this->worldPosition.has_value()) { this->newStatusText("Position: (%1, %2, %3)"_q @@ -56,6 +57,10 @@ { this->newStatusText("Position: <none>"_q); } + */ + // use a relatively high threshold so that we know when the grid is somewhat perpendicular so we can + // automatically change it properly + this->newStatusText("Change: %1"_q.arg(isGridPerpendicularToScreen(0.03f) ? "yes" : "no")); PartRenderer::mouseMoveEvent(event); } @@ -167,3 +172,23 @@ this->gridPlane = geom::planeFromTriangle(triangle); this->gridProgram->setGridMatrix(this->gridMatrix); } + +/** + * @brief Calculates if the screen is perpendicular to the current grid + * @return yes no + */ +bool Canvas::isGridPerpendicularToScreen(float threshold) const +{ + // Find out where the grid is projected on the screen + const QPoint gridOrigin2d = pointFToPoint(this->modelToScreenCoordinates(this->gridPlane.anchor)); + // Find out which direction the camera is looking at the grid origin in 3d + const glm::vec3 cameraDirection = glm::normalize(this->cameraLine(gridOrigin2d).direction); + // Compute the dot product. The parameters given are: + // - the normal of the grid plane, which is the vector from the grid origin perpendicular to the grid + // - the direction of the camera looking at the grid, which is the inverse of the vector from the grid + // origin towards the camera + // If the dot product between these two vectors is 0, the grid normal is perpendicular to the camera vector + // and the grid is perpendicular to the screen. + const float dot = glm::dot(glm::normalize(this->gridPlane.normal), glm::normalize(cameraDirection)); + return std::abs(dot) < threshold; +}
--- a/src/ui/canvas.h Sat Feb 29 23:51:03 2020 +0200 +++ b/src/ui/canvas.h Mon Mar 02 11:08:13 2020 +0200 @@ -24,6 +24,7 @@ void selectionChanged(const QSet<ldraw::Id>& newSelection); private: void updateGridMatrix(); + bool isGridPerpendicularToScreen(float threshold) const; std::optional<GridProgram> gridProgram; std::optional<glm::vec3> worldPosition; glm::mat4 gridMatrix;