diff --git a/src/definition/CameraDefinition.h b/src/definition/CameraDefinition.h index f93fd55..2daddf6 100644 --- a/src/definition/CameraDefinition.h +++ b/src/definition/CameraDefinition.h @@ -39,6 +39,8 @@ public: inline const Matrix4 &getTransformationMatrix() const {return projector;} inline VectorSpherical getDirectionSpherical() const {return direction;} inline CameraPerspective getPerspective() const {return perspective;} + inline double getWidth() const {return width;} + inline double getHeight() const {return height;} double getRealDepth(const Vector3 &projected) const; diff --git a/src/interface/modeler/quickapp/OpenGLView.cpp b/src/interface/modeler/quickapp/OpenGLView.cpp index e1a90f8..04f47a5 100644 --- a/src/interface/modeler/quickapp/OpenGLView.cpp +++ b/src/interface/modeler/quickapp/OpenGLView.cpp @@ -14,6 +14,7 @@ OpenGLView::OpenGLView(QQuickItem *parent) : renderer = NULL; setAcceptedMouseButtons(Qt::AllButtons); + setAcceptHoverEvents(true); mouse_button = Qt::NoButton; @@ -120,6 +121,13 @@ void OpenGLView::mouseMoveEvent(QMouseEvent *event) window->getCamera()->processScroll(-0.02 * factor * diff.x(), 0.02 * factor * diff.y()); } mouse_pos = event->windowPos(); + + renderer->setMouseLocation(event->pos().x(), height() - event->pos().y()); +} + +void OpenGLView::hoverMoveEvent(QHoverEvent *event) +{ + renderer->setMouseLocation(event->pos().x(), height() - event->pos().y()); } void OpenGLView::timerEvent(QTimerEvent *) diff --git a/src/interface/modeler/quickapp/OpenGLView.h b/src/interface/modeler/quickapp/OpenGLView.h index 58f2075..f007004 100644 --- a/src/interface/modeler/quickapp/OpenGLView.h +++ b/src/interface/modeler/quickapp/OpenGLView.h @@ -24,6 +24,7 @@ protected: virtual void mousePressEvent(QMouseEvent *event) override; virtual void mouseReleaseEvent(QMouseEvent *event) override; virtual void mouseMoveEvent(QMouseEvent *event) override; + virtual void hoverMoveEvent(QHoverEvent *event) override; virtual void timerEvent(QTimerEvent *event) override; private: diff --git a/src/render/opengl/OpenGLRenderer.cpp b/src/render/opengl/OpenGLRenderer.cpp index a2a3ae8..c3b8c65 100644 --- a/src/render/opengl/OpenGLRenderer.cpp +++ b/src/render/opengl/OpenGLRenderer.cpp @@ -10,6 +10,7 @@ #include "Scenery.h" #include "LightingManager.h" #include "Logs.h" +#include "Vector3.h" #include "GL/glu.h" // TEMP @@ -21,6 +22,13 @@ OpenGLRenderer::OpenGLRenderer(Scenery* scenery): vp_width = 1; vp_height = 1; + mouse_tracking = true; + mouse_x = 0; + mouse_y = 0; + mouse_projected = new Vector3(); + + view_matrix = new QMatrix4x4; + render_quality = 3; functions = new OpenGLFunctions(); @@ -40,6 +48,10 @@ OpenGLRenderer::~OpenGLRenderer() water->interrupt(); skybox->interrupt(); + delete mouse_projected; + + delete view_matrix; + delete skybox; delete water; delete terrain; @@ -140,6 +152,11 @@ void OpenGLRenderer::paint() terrain->render(); water->render(); + if (mouse_tracking) + { + updateMouseProjection(); + } + int error_code; while ((error_code = glGetError()) != GL_NO_ERROR) { @@ -172,6 +189,17 @@ void OpenGLRenderer::resume() terrain->resume(); } +void OpenGLRenderer::setMouseLocation(int x, int y) +{ + mouse_x = x; + mouse_y = y; +} + +const Vector3 &OpenGLRenderer::getMouseProjection() +{ + return *mouse_projected; +} + void OpenGLRenderer::cameraChangeEvent(CameraDefinition *camera) { // Get camera info @@ -191,9 +219,11 @@ void OpenGLRenderer::cameraChangeEvent(CameraDefinition *camera) projection.setToIdentity(); projection.perspective(perspective.yfov * 180.0 / M_PI, perspective.xratio, perspective.znear, perspective.zfar); + *view_matrix = projection * transform; + // Set in shaders shared_state->set("cameraLocation", location); - shared_state->set("viewMatrix", projection * transform); + shared_state->set("viewMatrix", *view_matrix); } double OpenGLRenderer::getPrecision(const Vector3 &) @@ -205,3 +235,15 @@ Color OpenGLRenderer::applyMediumTraversal(Vector3, Color color) { return color; } + +void OpenGLRenderer::updateMouseProjection() +{ + GLfloat z; + functions->glReadPixels(mouse_x, mouse_y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z); + + QVector4D located(mouse_x / render_camera->getWidth(), mouse_y / render_camera->getHeight(), z, 1.0); + QVector4D unprojected = view_matrix->inverted() * 2.0 * (located - QVector4D(0.5, 0.5, 0.5, 0.5)); + *mouse_projected = Vector3(unprojected.x() / unprojected.w(), unprojected.y() / unprojected.w(), unprojected.z() / unprojected.w()); + + shared_state->set("mouseProjection", *mouse_projected); +} diff --git a/src/render/opengl/OpenGLRenderer.h b/src/render/opengl/OpenGLRenderer.h index 0d0de51..265cca6 100644 --- a/src/render/opengl/OpenGLRenderer.h +++ b/src/render/opengl/OpenGLRenderer.h @@ -5,6 +5,8 @@ #include "SoftwareRenderer.h" +class QMatrix4x4; + namespace paysages { namespace opengl { @@ -42,6 +44,16 @@ public: */ void resume(); + /** + * Set the current mouse location, for use by getMouseProjection(). + */ + void setMouseLocation(int x, int y); + + /** + * Get the coordinates of the mouse, projected in world space. + */ + const Vector3 &getMouseProjection(); + /** * Change the camera location. */ @@ -54,12 +66,25 @@ public: virtual double getPrecision(const Vector3 &location) override; virtual Color applyMediumTraversal(Vector3 location, Color color) override; +private: + /** + * Update the mouse_projected member. + */ + void updateMouseProjection(); + private: bool ready; bool paused; int vp_width; int vp_height; + bool mouse_tracking; + int mouse_x; + int mouse_y; + Vector3 *mouse_projected; + + QMatrix4x4 *view_matrix; + OpenGLFunctions* functions; OpenGLSharedState* shared_state; diff --git a/src/render/opengl/OpenGLTerrain.cpp b/src/render/opengl/OpenGLTerrain.cpp index ee6aee2..8df2fd8 100644 --- a/src/render/opengl/OpenGLTerrain.cpp +++ b/src/render/opengl/OpenGLTerrain.cpp @@ -63,6 +63,7 @@ void OpenGLTerrain::initialize() program->addFragmentSource("atmosphere"); program->addFragmentSource("tonemapping"); program->addFragmentSource("fadeout"); + program->addFragmentSource("ui"); program->addFragmentSource("terrain"); // Add terrain chunks diff --git a/src/render/opengl/OpenGLWater.cpp b/src/render/opengl/OpenGLWater.cpp index 81c6289..5406e1e 100644 --- a/src/render/opengl/OpenGLWater.cpp +++ b/src/render/opengl/OpenGLWater.cpp @@ -30,6 +30,7 @@ void OpenGLWater::initialize() program->addFragmentSource("atmosphere"); program->addFragmentSource("tonemapping"); program->addFragmentSource("fadeout"); + program->addFragmentSource("ui"); program->addFragmentSource("noise"); program->addFragmentSource("water"); diff --git a/src/render/opengl/shaders/resources.qrc b/src/render/opengl/shaders/resources.qrc index ed4c445..68f3f23 100644 --- a/src/render/opengl/shaders/resources.qrc +++ b/src/render/opengl/shaders/resources.qrc @@ -10,5 +10,6 @@ terrain.vert fadeout.frag noise.frag + ui.frag diff --git a/src/render/opengl/shaders/terrain.frag b/src/render/opengl/shaders/terrain.frag index de2f60c..5343e7f 100644 --- a/src/render/opengl/shaders/terrain.frag +++ b/src/render/opengl/shaders/terrain.frag @@ -9,5 +9,7 @@ void main(void) gl_FragColor = applyToneMapping(gl_FragColor); + gl_FragColor = applyMouseTracking(unprojected, gl_FragColor); + gl_FragColor.a = distanceFadeout(); } diff --git a/src/render/opengl/shaders/ui.frag b/src/render/opengl/shaders/ui.frag new file mode 100644 index 0000000..1c399a8 --- /dev/null +++ b/src/render/opengl/shaders/ui.frag @@ -0,0 +1,14 @@ +uniform vec3 mouseProjection; + +vec4 applyMouseTracking(vec3 location, vec4 color) +{ + float dist = length(location - mouseProjection); + if (dist > 2.0) + { + return color; + } + else + { + return mix(color, vec4(1.0, 0.0, 0.0, 1.0), 1.0 - dist / 2.0); + } +} diff --git a/src/render/opengl/shaders/water.frag b/src/render/opengl/shaders/water.frag index d6b5279..4a873a3 100644 --- a/src/render/opengl/shaders/water.frag +++ b/src/render/opengl/shaders/water.frag @@ -15,5 +15,7 @@ void main(void) gl_FragColor = applyToneMapping(gl_FragColor); + gl_FragColor = applyMouseTracking(unprojected, gl_FragColor); + gl_FragColor.a = distanceFadeout(); }