--- a/src/ui/canvas.cpp Sat Feb 29 23:43:38 2020 +0200 +++ b/src/ui/canvas.cpp Sat Feb 29 23:51:03 2020 +0200 @@ -30,8 +30,19 @@ this->worldPosition = this->screenToModelCoordinates(event->pos(), this->gridPlane); if (this->worldPosition.has_value()) { + /* + * Snap the position to grid. This procedure is basically the "change of basis" and almost follows the + * A⁻¹ × M × A formula which is used to perform a transformation in some other coordinate system, except + * we actually use the inverted matrix first and the regular one last to perform the transformation of + * grid coordinates in our XY coordinate system. Also, we're rounding the coordinates which is obviously + * not a linear transformation, but fits the pattern anyway. + */ + // First transform the coordinates to the XY plane... this->worldPosition = glm::inverse(this->gridMatrix) * glm::vec4{*this->worldPosition, 1}; + // Then round the coordinates to integer precision... this->worldPosition = glm::round(*this->worldPosition); + // And finally transform it back to grid coordinates by transforming it with the + // grid matrix. this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1}; } if (this->worldPosition.has_value())