Thu, 27 Feb 2020 11:56:41 +0200
use glm::unProject to implement screenToModelCoordinates
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 Wed Feb 26 22:26:05 2020 +0200 +++ b/src/gl/partrenderer.cpp Thu Feb 27 11:56:41 2020 +0200 @@ -71,6 +71,7 @@ void PartRenderer::resizeGL(int width, int height) { + this->viewportVector = {0, 0, width, height}; glViewport(0, 0, width, height); this->projectionMatrix = glm::perspective( glm::radians(45.0f), @@ -96,25 +97,11 @@ throw std::runtime_error{"Bad vbo class passed to getGlTypeForVboClass"}; } -#include <QPainter> void PartRenderer::paintGL() { glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); this->renderScene(); - QPainter painter{this}; - painter.setPen(Qt::white); - painter.setBrush(Qt::red); - for (float x : {1, -1}) - { - for (float y : {1, -1}) - { - for (float z : {1, -1}) - { - painter.drawEllipse(this->modelToScreenCoordinates({x, y, z}), 10, 10); - } - } - } } void PartRenderer::renderScene() @@ -301,12 +288,8 @@ std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point) { - glm::vec3 pp = {point.x(), this->height() - point.y(), 1}; - glm::mat4 matrix; - matrix = this->projectionMatrix * this->viewMatrix * glm::mat4_cast(this->modelQuaternion); - matrix = glm::transpose(glm::inverse(matrix)); - auto p1 = matrix * glm::vec4{pp.x, pp.y, 0, 1}; - auto p2 = matrix * glm::vec4{pp.x, pp.y, 1, 1}; + 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); } @@ -321,6 +304,15 @@ return toQPointF(pp); } +glm::vec3 PartRenderer::unproject(const glm::vec3& win) +{ + return glm::unProject( + glm::vec3{win.x, this->height() - win.y, win.z}, + this->viewMatrix * glm::mat4_cast(this->modelQuaternion), + this->projectionMatrix, + viewportVector); +} + ldraw::Id PartRenderer::pick(const QPoint& where) { const gl::RenderStyle oldRenderStyle = this->renderPreferences.style;
--- a/src/gl/partrenderer.h Wed Feb 26 22:26:05 2020 +0200 +++ b/src/gl/partrenderer.h Thu Feb 27 11:56:41 2020 +0200 @@ -24,6 +24,7 @@ ~PartRenderer() override; void setRenderPreferences(const gl::RenderPreferences& newPreferences); static glm::vec3 viewport(const glm::vec3& point, float width, float height); + static glm::vec3 antiviewport(const glm::vec3& point, float width, float height); protected: ldraw::Id pick(const QPoint& where); void initializeGL() override; @@ -39,6 +40,7 @@ ldraw::Id highlighted = ldraw::NULL_ID; std::optional<glm::vec3> screenToModelCoordinates(const QPoint& point); QPointF modelToScreenCoordinates(const glm::vec3& point); + glm::vec3 unproject(const glm::vec3& win); private: void setFragmentStyle(gl::FragmentStyle fragStyle); void renderAllArrays(); @@ -50,6 +52,7 @@ gl::RenderPreferences renderPreferences; glm::mat4 projectionMatrix; glm::mat4 viewMatrix; + glm::vec4 viewportVector; glm::quat modelQuaternion; std::optional<GridProgram> gridProgram; static constexpr double MIN_ZOOM = 0.0;
--- a/src/ui/canvas.cpp Wed Feb 26 22:26:05 2020 +0200 +++ b/src/ui/canvas.cpp Thu Feb 27 11:56:41 2020 +0200 @@ -1,4 +1,5 @@ #include <QMouseEvent> +#include <QPainter> #include "canvas.h" Canvas::Canvas( @@ -22,24 +23,26 @@ void Canvas::mouseMoveEvent(QMouseEvent* event) { -#if 0 - std::optional<glm::vec3> p = this->cameraToGrid(event->pos()); - if (p.has_value()) + const ldraw::Id id = this->pick(event->pos()); + this->highlighted = id; + this->totalMouseMove += (event->pos() - this->lastMousePosition).manhattanLength(); + this->lastMousePosition = event->pos(); + this->worldPosition = this->screenToModelCoordinates(this->lastMousePosition); + if (this->worldPosition.has_value()) { - this->newStatusText("Position: (%1, %2, %3)"_q.arg(p->x).arg(p->y).arg(p->z)); + this->worldPosition = glm::round(*this->worldPosition); + } + if (this->worldPosition.has_value()) + { + this->newStatusText("Position: (%1, %2, %3)"_q + .arg(this->worldPosition->x) + .arg(this->worldPosition->y) + .arg(this->worldPosition->z)); } else { this->newStatusText("Position: <none>"_q); } -#else - const QPointF originAtCamera = this->modelToScreenCoordinates({1, 1, 1}); - this->newStatusText("{1,1,1} is at (%1, %2), cursor at (%3, %4)"_q.arg(originAtCamera.x()).arg(originAtCamera.y()).arg(event->pos().x()).arg(event->pos().y())); -#endif - const ldraw::Id id = this->pick(event->pos()); - this->highlighted = id; - this->totalMouseMove += (event->pos() - this->lastMousePosition).manhattanLength(); - this->lastMousePosition = event->pos(); PartRenderer::mouseMoveEvent(event); } @@ -68,3 +71,16 @@ } PartRenderer::mouseReleaseEvent(event); } + +void Canvas::paintGL() +{ + PartRenderer::paintGL(); + if (this->worldPosition.has_value()) + { + QPainter painter{this}; + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(Qt::black); + painter.setBrush(Qt::green); + painter.drawEllipse(this->modelToScreenCoordinates(*this->worldPosition), 10, 10); + } +}
--- a/src/ui/canvas.h Wed Feb 26 22:26:05 2020 +0200 +++ b/src/ui/canvas.h Thu Feb 27 11:56:41 2020 +0200 @@ -16,11 +16,13 @@ void mouseMoveEvent(QMouseEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; + void paintGL() override; signals: void newStatusText(const QString& newStatusText); void selectionChanged(const QSet<ldraw::Id>& newSelection); private: QPoint lastMousePosition; + std::optional<glm::vec3> worldPosition; int totalMouseMove = 0; QSet<ldraw::Id> selection; };