# HG changeset patch # User Teemu Piippo # Date 1583012618 -7200 # Node ID f99d52b1646b924040027d5d730a4a8990a2598f # Parent f7dd937667a5bce81f2abf4572c2accb03271873 grid snapping now also works with transformed grids diff -r f7dd937667a5 -r f99d52b1646b src/geometry.cpp --- a/src/geometry.cpp Fri Feb 28 19:24:33 2020 +0200 +++ b/src/geometry.cpp Sat Feb 29 23:43:38 2020 +0200 @@ -1,3 +1,4 @@ +#include #include "geometry.h" /** @@ -38,7 +39,7 @@ */ geom::Plane geom::planeFromTriangle(const geom::Triangle& triangle) { - return geom::Plane{triangle.points[0], normalVector(triangle)}; + return geom::Plane{normalVector(triangle), triangle.points[0]}; } /** @@ -53,3 +54,31 @@ triangle.points[1] - triangle.points[0], triangle.points[2] - triangle.points[0])); } + +/** + * @brief Extracts the scaling component of the specified matrix into a vector and returns both the scaling + * components as well as the unscaled matrix. + * @param matrix Matrix to compute + * @return scaling vector and unscaled matrix + */ +geom::ScalingExtract geom::extractScaling(const glm::mat4& matrix) +{ + geom::ScalingExtract result; + result.scaling = geom::scalingVector(matrix); + result.unscaled = glm::scale(matrix, 1.0f / result.scaling); + return result; +} + +/** + * @brief Computes the scaling vector, which contains the scaling of the specified matrix + * @param matrix + * @return scaling vector + */ +glm::vec3 geom::scalingVector(const glm::mat4 matrix) +{ + auto component = [](const glm::mat4& matrix, const int i) -> float + { + return std::hypot(std::hypot(matrix[i][0], matrix[i][1]), matrix[i][2]); + }; + return glm::vec3{component(matrix, 0), component(matrix, 1), component(matrix, 2)}; +} diff -r f7dd937667a5 -r f99d52b1646b src/geometry.h --- a/src/geometry.h Fri Feb 28 19:24:33 2020 +0200 +++ b/src/geometry.h Sat Feb 29 23:43:38 2020 +0200 @@ -30,5 +30,12 @@ Line lineFromPoints(const glm::vec3& point_1, const glm::vec3 point_2); Plane planeFromTriangle(const Triangle& triangle); glm::vec3 normalVector(const Triangle& triangle); - std::optional linePlaneIntersection(const Line& line, const Plane& plane, const float epsilon = 1e-6); + std::optional linePlaneIntersection(const Line& line, const Plane& plane, const float epsilon = 1e-6f); + glm::vec3 scalingVector(const glm::mat4 matrix); + struct ScalingExtract + { + glm::vec3 scaling; + glm::mat4 unscaled; + }; + ScalingExtract extractScaling(const glm::mat4& matrix); } diff -r f7dd937667a5 -r f99d52b1646b src/gl/gridprogram.cpp --- a/src/gl/gridprogram.cpp Fri Feb 28 19:24:33 2020 +0200 +++ b/src/gl/gridprogram.cpp Sat Feb 29 23:43:38 2020 +0200 @@ -28,11 +28,11 @@ uniform mat4 model; smooth out vec2 ex_uv; const mat4 stretch = mat4(vec4(10000, 0, 0, 0), vec4(0, 10000, 0, 0), vec4(0, 0, 10000, 0), vec4(0, 0, 0, 1)); -const mat4 gridmatrix = mat4(vec4(1, 0, 0, 0), vec4(0, 1, 0, 0), vec4(0, 0, 1, 0), vec4(0, 0, 0, 1)); +uniform mat4 grid; void main() { - gl_Position = projection * view * model * gridmatrix * stretch * vec4(in_position, 0.0, 1.0); + gl_Position = projection * view * model * grid * stretch * vec4(in_position, 0.0, 1.0); ex_uv = in_position; } )"; @@ -99,27 +99,29 @@ void GridProgram::setViewMatrix(const glm::mat4& newViewMatrix) { - Q_ASSERT(this->isInitialized); - this->program->bind(); - this->program->setUniformMatrix("view", newViewMatrix); - this->program->release(); - this->checkForGLErrors(); + this->setMatrix("view", newViewMatrix); } void GridProgram::setProjectionMatrix(const glm::mat4& newProjectionMatrix) { - Q_ASSERT(this->isInitialized); - this->program->bind(); - this->program->setUniformMatrix("projection", newProjectionMatrix); - this->program->release(); - this->checkForGLErrors(); + this->setMatrix("projection", newProjectionMatrix); } void GridProgram::setModelMatrix(const glm::mat4& newModelMatrix) { + this->setMatrix("model", newModelMatrix); +} + +void GridProgram::setGridMatrix(const glm::mat4& newGridMatrix) +{ + this->setMatrix("grid", newGridMatrix); +} + +void GridProgram::setMatrix(const char* name, const glm::mat4& matrix) +{ Q_ASSERT(this->isInitialized); this->program->bind(); - this->program->setUniformMatrix("model", newModelMatrix); + this->program->setUniformMatrix(name, matrix); this->program->release(); this->checkForGLErrors(); } diff -r f7dd937667a5 -r f99d52b1646b src/gl/gridprogram.h --- a/src/gl/gridprogram.h Fri Feb 28 19:24:33 2020 +0200 +++ b/src/gl/gridprogram.h Sat Feb 29 23:43:38 2020 +0200 @@ -31,11 +31,13 @@ void setViewMatrix(const glm::mat4& newViewMatrix); void setProjectionMatrix(const glm::mat4& newProjectionMatrix); void setModelMatrix(const glm::mat4& newModelMatrix); + void setGridMatrix(const glm::mat4& newGridMatrix); void setGridColor(const QColor& newGridColor); void operator=(GridProgram) = delete; void draw(); void teardown(); private: + void setMatrix(const char* name, const glm::mat4& matrix); void checkForGLErrors(); bool isInitialized = false; QOpenGLBuffer buffer; diff -r f7dd937667a5 -r f99d52b1646b src/main.h --- a/src/main.h Fri Feb 28 19:24:33 2020 +0200 +++ b/src/main.h Sat Feb 29 23:43:38 2020 +0200 @@ -87,3 +87,27 @@ { vector.reserve(vector.size() + amount); } + +inline QString vectorToString(const glm::vec2& vec) +{ + return "(%1, %2)"_q + .arg(toDouble(vec.x)) + .arg(toDouble(vec.y)); +} + +inline QString vectorToString(const glm::vec3& vec) +{ + return "(%1, %2, %3)"_q + .arg(toDouble(vec.x)) + .arg(toDouble(vec.y)) + .arg(toDouble(vec.z)); +} + +inline QString vectorToString(const glm::vec4& vec) +{ + return "(%1, %2, %3, %4)"_q + .arg(toDouble(vec.x)) + .arg(toDouble(vec.y)) + .arg(toDouble(vec.z)) + .arg(toDouble(vec.w)); +} diff -r f7dd937667a5 -r f99d52b1646b src/ui/canvas.cpp --- a/src/ui/canvas.cpp Fri Feb 28 19:24:33 2020 +0200 +++ b/src/ui/canvas.cpp Sat Feb 29 23:43:38 2020 +0200 @@ -22,23 +22,17 @@ this->update(); } -QString vectorToString(const glm::vec3& vec) -{ - return "(%1, %2, %3)"_q - .arg(toDouble(vec.x)) - .arg(toDouble(vec.y)) - .arg(toDouble(vec.z)); -} - void Canvas::mouseMoveEvent(QMouseEvent* event) { const ldraw::Id id = this->pick(event->pos()); this->highlighted = id; this->totalMouseMove += (event->pos() - this->lastMousePosition).manhattanLength(); - this->worldPosition = this->screenToModelCoordinates(event->pos(), geom::XY); + this->worldPosition = this->screenToModelCoordinates(event->pos(), this->gridPlane); if (this->worldPosition.has_value()) { + this->worldPosition = glm::inverse(this->gridMatrix) * glm::vec4{*this->worldPosition, 1}; this->worldPosition = glm::round(*this->worldPosition); + this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1}; } if (this->worldPosition.has_value()) { @@ -107,6 +101,13 @@ } }); PartRenderer::initializeGL(); + this->gridMatrix = glm::mat4{ + {-4, 0, 0, 0}, + {0, 6.9266, -3.6955, 0}, + {0, -16.7222, -1.5307, 0}, + {0, -13.273, -9.255, 1}, + }; + this->updateGridMatrix(); } void Canvas::paintGL() @@ -127,4 +128,31 @@ painter.setPen(Qt::white); painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition)); } + { + QPainter axisPainter{this}; + axisPainter.setRenderHint(QPainter::Antialiasing); + axisPainter.setPen(Qt::red); + axisPainter.drawLine( + this->modelToScreenCoordinates({10, 0, 0}), + this->modelToScreenCoordinates({-10, 0, 0})); + axisPainter.setPen(Qt::green); + axisPainter.drawLine( + this->modelToScreenCoordinates({0, 10, 0}), + this->modelToScreenCoordinates({0, -10, 0})); + axisPainter.setPen(Qt::blue); + axisPainter.drawLine( + this->modelToScreenCoordinates({0, 0, 10}), + this->modelToScreenCoordinates({0, 0, -10})); + } } + +void Canvas::updateGridMatrix() +{ + const geom::Triangle triangle { + this->gridMatrix * glm::vec4{0, 0, 0, 1}, + this->gridMatrix * glm::vec4{1, 0, 0, 1}, + this->gridMatrix * glm::vec4{0, 1, 0, 1}, + }; + this->gridPlane = geom::planeFromTriangle(triangle); + this->gridProgram->setGridMatrix(this->gridMatrix); +} diff -r f7dd937667a5 -r f99d52b1646b src/ui/canvas.h --- a/src/ui/canvas.h Fri Feb 28 19:24:33 2020 +0200 +++ b/src/ui/canvas.h Sat Feb 29 23:43:38 2020 +0200 @@ -23,8 +23,11 @@ void newStatusText(const QString& newStatusText); void selectionChanged(const QSet& newSelection); private: + void updateGridMatrix(); std::optional gridProgram; std::optional worldPosition; + glm::mat4 gridMatrix; + geom::Plane gridPlane; int totalMouseMove = 0; QSet selection; };