# HG changeset patch # User Teemu Piippo # Date 1582676467 -7200 # Node ID cb81ecb5fb2364889748dedf0a346f31c3099398 # Parent a4055f67b9c794d0ed2fd870af85ecf2f9f4e2c8 grid stuff diff -r a4055f67b9c7 -r cb81ecb5fb23 CMakeLists.txt --- a/CMakeLists.txt Thu Feb 13 15:25:01 2020 +0200 +++ b/CMakeLists.txt Wed Feb 26 02:21:07 2020 +0200 @@ -25,6 +25,7 @@ src/colors.cpp src/document.cpp src/documentmanager.cpp + src/geometry.cpp src/libraries.cpp src/invert.cpp src/main.cpp @@ -58,6 +59,7 @@ src/colors.h src/document.h src/documentmanager.h + src/geometry.h src/header.h src/invert.h src/libraries.h diff -r a4055f67b9c7 -r cb81ecb5fb23 src/basics.h --- a/src/basics.h Thu Feb 13 15:25:01 2020 +0200 +++ b/src/basics.h Wed Feb 26 02:21:07 2020 +0200 @@ -108,30 +108,48 @@ /** -* @brief casts double and long double - and only those types - to float -* @param[in] x double or long double to cast +* @brief casts floating point values to float, converting non-floating point values causes an error +* @param[in] x floating point value to cast * @returns float */ template -auto doubleToFloat(T x) - -> std::enable_if_t< - std::is_same_v, double> || - std::is_same_v, long double - >, float> +auto toFloat(T x) -> std::enable_if_t, float> { return static_cast(x); } /** -* @brief Casts float - and only float - to double -* @param[in] x float to cast +* @brief casts floating point values to double, converting non-floating point values causes an error +* @param[in] x floating point value to cast * @returns double */ template -auto floatToDouble(T x) - -> std::enable_if_t, float>, double> +auto toDouble(T x) -> std::enable_if_t, double> { return static_cast(x); } + +template +inline QPoint toQPoint(const glm::vec& vec) +{ + return {static_cast(vec.x), static_cast(vec.y)}; +} + +template +inline QPointF toQPointF(const glm::vec& vec) +{ + return {toDouble(vec.x), toDouble(vec.y)}; +} + +inline glm::vec2 toVec2(const QPoint& point) +{ + return {point.x(), point.y()}; +} + +inline glm::vec2 toVec2(const QPointF& point) +{ + return {point.x(), point.y()}; +} + Q_DECLARE_METATYPE(glm::vec3) Q_DECLARE_METATYPE(glm::mat4) diff -r a4055f67b9c7 -r cb81ecb5fb23 src/geometry.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/geometry.cpp Wed Feb 26 02:21:07 2020 +0200 @@ -0,0 +1,55 @@ +#include "geometry.h" + +/** + * @brief Computes a line from two points + * @param point_1 + * @param point_2 + * @return line + */ +geom::Line geom::lineFromPoints(const glm::vec3& point_1, const glm::vec3 point_2) +{ + return {point_2 - point_1, point_1}; +} + +/** + * @brief Computes line-plane intersection + * @param line + * @param plane + * @return point of intersection. Does not return a value if the line is in parallel to the plane. + */ +std::optional geom::linePlaneIntersection(const geom::Line& line, const geom::Plane& plane) +{ + const float denominator = glm::dot(line.direction, plane.normal); + if (std::abs(denominator) < 1e-8f) + { + return {}; + } + else + { + const float d = glm::dot(plane.anchor - line.anchor, plane.normal) / denominator; + return line.anchor + d * line.direction; + } +} + +/** + * @brief Computes the plane of a triangle + * @param triangle + * @return plane + */ +geom::Plane geom::planeFromTriangle(const geom::Triangle& triangle) +{ + return geom::Plane{triangle.points[0], normalVector(triangle)}; +} + +/** + * @brief Computes the normal vector of a triangle + * @param triangle + * @return normal vector + */ +glm::vec3 geom::normalVector(const geom::Triangle& triangle) +{ + return glm::normalize( + glm::cross( + triangle.points[1] - triangle.points[0], + triangle.points[2] - triangle.points[0])); +} diff -r a4055f67b9c7 -r cb81ecb5fb23 src/geometry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/geometry.h Wed Feb 26 02:21:07 2020 +0200 @@ -0,0 +1,34 @@ +#pragma once +#include "basics.h" + +namespace geom +{ + struct Plane + { + glm::vec3 normal; + glm::vec3 anchor; + }; + + struct Line + { + glm::vec3 direction; + glm::vec3 anchor; + }; + + template + struct Polygon + { + glm::vec3 points[N]; + }; + + inline const glm::vec3 origin = {0, 0, 0}; + inline const Plane XY = {{0, 0, 1}, origin}; + inline const Plane XZ = {{0, 1, 0}, origin}; + inline const Plane YZ = {{1, 0, 0}, origin}; + using Triangle = Polygon<3>; + + 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); +} diff -r a4055f67b9c7 -r cb81ecb5fb23 src/gl/common.h --- a/src/gl/common.h Thu Feb 13 15:25:01 2020 +0200 +++ b/src/gl/common.h Wed Feb 26 02:21:07 2020 +0200 @@ -37,6 +37,14 @@ const char* vertexShaderSource, const char* fragmentShaderSource); void checkForGLErrors(QWidget* parent); + inline glm::vec3 colorToVector3(const QColor& color) + { + return {toFloat(color.redF()), toFloat(color.greenF()), toFloat(color.blueF())}; + } + inline glm::vec4 colorToVector4(const QColor& color) + { + return {gl::colorToVector3(color), toFloat(color.alphaF())}; + } } class gl::ShaderProgram : public QOpenGLShaderProgram @@ -50,11 +58,10 @@ const float (*array)[4][4] = reinterpret_cast(glm::value_ptr(value)); this->setUniformValue(uniformName, *array); } - template - void setUniformVector(const char* uniformName, const glm::vec& value) + template + void setUniformVector(const char* uniformName, const glm::vec<4, Float, Prec>& value) { - const Float (*array)[N] = reinterpret_cast(glm::value_ptr(value)); - this->setUniformValue(uniformName, array); + this->setUniformValue(uniformName, value.x, value.y, value.z, value.w); } }; diff -r a4055f67b9c7 -r cb81ecb5fb23 src/gl/gridprogram.cpp --- a/src/gl/gridprogram.cpp Thu Feb 13 15:25:01 2020 +0200 +++ b/src/gl/gridprogram.cpp Wed Feb 26 02:21:07 2020 +0200 @@ -42,7 +42,7 @@ out vec4 color; smooth in vec2 ex_uv; -const vec4 lineColor = vec4(1.0, 1.0, 1.0, 0.75); +uniform vec4 gridColor; const float pi = 3.14159265f; void main(void) @@ -58,7 +58,7 @@ /* add dashes */ d *= (1 + cos(ex_uv.y / 0.00001f * pi)) * 0.5f; d *= (1 + cos(ex_uv.x / 0.00001f * pi)) * 0.5f; - color = vec4(lineColor.xyz, d); + color = vec4(gridColor.xyz, gridColor.w * d); } )"; @@ -89,6 +89,7 @@ this->vertexArrayObject.bind(); this->program->enableAttributeArray(0); this->program->setAttributeBuffer(0, GL_FLOAT, 0, 2, 0); + this->program->setUniformVector("gridColor", this->gridColor); this->vertexArrayObject.release(); this->buffer.release(); this->program->release(); @@ -123,6 +124,22 @@ this->checkForGLErrors(); } +void GridProgram::setGridColor(const QColor& newGridColor) +{ + const glm::vec4 vec = gl::colorToVector4(newGridColor); + if (this->isInitialized) + { + this->program->bind(); + this->program->setUniformVector("gridColor", vec); + this->program->release(); + this->checkForGLErrors(); + } + else + { + this->gridColor = vec; + } +} + void GridProgram::draw() { this->program->bind(); diff -r a4055f67b9c7 -r cb81ecb5fb23 src/gl/gridprogram.h --- a/src/gl/gridprogram.h Thu Feb 13 15:25:01 2020 +0200 +++ b/src/gl/gridprogram.h Wed Feb 26 02:21:07 2020 +0200 @@ -31,6 +31,7 @@ void setViewMatrix(const glm::mat4& newViewMatrix); void setProjectionMatrix(const glm::mat4& newProjectionMatrix); void setModelMatrix(const glm::mat4& newModelMatrix); + void setGridColor(const QColor& newGridColor); void operator=(GridProgram) = delete; void draw(); void teardown(); @@ -41,5 +42,6 @@ QOpenGLShader vertexShader; QOpenGLShader fragmentShader; std::optional program{std::nullopt}; + glm::vec4 gridColor = {1.0f, 1.0f, 1.0f, 0.75f}; QOpenGLVertexArrayObject vertexArrayObject; }; diff -r a4055f67b9c7 -r cb81ecb5fb23 src/gl/partrenderer.cpp --- a/src/gl/partrenderer.cpp Thu Feb 13 15:25:01 2020 +0200 +++ b/src/gl/partrenderer.cpp Wed Feb 26 02:21:07 2020 +0200 @@ -22,6 +22,7 @@ #include #include #include +#include "geometry.h" #include "partrenderer.h" PartRenderer::PartRenderer( @@ -62,6 +63,8 @@ this->initialized = true; this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0}); this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0}); + this->setupBackgroundColor(); + this->updateModelMatrix(); this->updateViewMatrix(); this->update(); } @@ -69,6 +72,11 @@ void PartRenderer::resizeGL(int width, int height) { glViewport(0, 0, width, height); + this->viewportMatrix = { + {1, 0, 0}, + {0, 1, 0}, + {width * 0.5f, height * 0.5f, 1} + }; this->projectionMatrix = glm::perspective( glm::radians(45.0f), static_cast(width) / static_cast(height), @@ -194,6 +202,23 @@ this->gridProgram->setViewMatrix(this->viewMatrix); } +void PartRenderer::updateModelMatrix() +{ + const glm::mat4 modelMatrix = glm::mat4_cast(this->modelQuaternion); + this->compiler->setUniformMatrix("modelMatrix", modelMatrix); + this->gridProgram->setModelMatrix(modelMatrix); + this->update(); +} + +void PartRenderer::setupBackgroundColor() +{ + if (this->gridProgram.has_value()) + { + const bool isDark = luma(this->renderPreferences.backgroundColor) < 0.25; + this->gridProgram->setGridColor(isDark ? Qt::white : Qt::black); + } +} + void PartRenderer::renderVao(const gl::ArrayClass arrayClass) { this->compiler->bindVertexArray(arrayClass); @@ -246,10 +271,7 @@ const glm::quat q_x = glm::angleAxis(scalar * move_x, glm::vec3{0, -1, 0}); const glm::quat q_y = glm::angleAxis(scalar * move_y, glm::vec3{-1, 0, 0}); this->modelQuaternion = q_x * q_y * this->modelQuaternion; - const glm::mat4 modelMatrix = glm::mat4_cast(this->modelQuaternion); - this->compiler->setUniformMatrix("modelMatrix", modelMatrix); - this->gridProgram->setModelMatrix(modelMatrix); - this->update(); + this->updateModelMatrix(); } this->lastMousePosition = pointToPointF(event->pos()); } @@ -263,6 +285,33 @@ this->update(); } +std::optional PartRenderer::cameraToGrid(const QPoint& point) +{ + glm::vec3 pp = {point.x(), this->height() - point.y(), 1}; + pp = glm::inverse(this->viewportMatrix) * pp; + 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}; + geom::Line line = geom::lineFromPoints(p1, p2); + return geom::linePlaneIntersection(line, geom::XY); +} + +QPointF PartRenderer::worldToCamera(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->viewportMatrix * glm::vec3{p.x, p.y, 1}; + return toQPointF(pp); + /* + const glm::mat4 matrix = this->projectionMatrix * this->viewMatrix * glm::mat4_cast(this->modelQuaternion); + return toQPointF(matrix * glm::vec4{point, 1}); + */ +} + ldraw::Id PartRenderer::pick(const QPoint& where) { const gl::RenderStyle oldRenderStyle = this->renderPreferences.style; @@ -299,6 +348,8 @@ if (mainColorChanged or backgroundColorChanged) { this->compiler->build(this->model, this->documents, this->renderPreferences); + this->setupBackgroundColor(); + } this->update(); } diff -r a4055f67b9c7 -r cb81ecb5fb23 src/gl/partrenderer.h --- a/src/gl/partrenderer.h Thu Feb 13 15:25:01 2020 +0200 +++ b/src/gl/partrenderer.h Wed Feb 26 02:21:07 2020 +0200 @@ -35,15 +35,20 @@ const ldraw::ColorTable& colorTable; gl::Compiler* const compiler; ldraw::Id highlighted = ldraw::NULL_ID; + std::optional cameraToGrid(const QPoint& point); + QPointF worldToCamera(const glm::vec3& point); private: void setFragmentStyle(gl::FragmentStyle fragStyle); void renderAllArrays(); void renderScene(); void updateViewMatrix(); + void updateModelMatrix(); + void setupBackgroundColor(); QPointF lastMousePosition; gl::RenderPreferences renderPreferences; glm::mat4 projectionMatrix; glm::mat4 viewMatrix; + glm::mat3 viewportMatrix; glm::quat modelQuaternion; std::optional gridProgram; static constexpr double MIN_ZOOM = 0.0; diff -r a4055f67b9c7 -r cb81ecb5fb23 src/main.h --- a/src/main.h Thu Feb 13 15:25:01 2020 +0200 +++ b/src/main.h Wed Feb 26 02:21:07 2020 +0200 @@ -24,6 +24,7 @@ #include "basics.h" #include "utility.h" #include "maths.h" +#include "geometry.h" namespace settingGroups { diff -r a4055f67b9c7 -r cb81ecb5fb23 src/maths.h --- a/src/maths.h Thu Feb 13 15:25:01 2020 +0200 +++ b/src/maths.h Wed Feb 26 02:21:07 2020 +0200 @@ -90,6 +90,8 @@ { return arg + sum(rest...); } + + std::optional linePlaneIntersection(); } inline unsigned int qHash(const glm::vec3& key) diff -r a4055f67b9c7 -r cb81ecb5fb23 src/ui/canvas.cpp --- a/src/ui/canvas.cpp Thu Feb 13 15:25:01 2020 +0200 +++ b/src/ui/canvas.cpp Wed Feb 26 02:21:07 2020 +0200 @@ -22,8 +22,21 @@ void Canvas::mouseMoveEvent(QMouseEvent* event) { +#if 0 + std::optional p = this->cameraToGrid(event->pos()); + if (p.has_value()) + { + this->newStatusText("Position: (%1, %2, %3)"_q.arg(p->x).arg(p->y).arg(p->z)); + } + else + { + this->newStatusText("Position: "_q); + } +#else + const QPointF originAtCamera = this->worldToCamera({1, 1, 1}); + this->newStatusText("Origin 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->newStatusText("Selected: %1"_q.arg(id.value)); this->highlighted = id; this->totalMouseMove += (event->pos() - this->lastMousePosition).manhattanLength(); this->lastMousePosition = event->pos();