Перевод Qmatrix4x4 не дает никакого эффекта - PullRequest
0 голосов
/ 02 февраля 2019

У меня не было большого опыта в opengl, поэтому извините, если вопрос глупый.

Я пытаюсь переместить треугольник с помощью mouseMoveEvent, переводя поле Qmatrix4x4 в моем классе glView.Когда я ничего не делал (перспектива, переводил с матрицей) и просто вызывал m_program->setUniformValue(m_matrixUniform, m_matrix), все работает нормально, но если я просто делаю this->m_matrix=matrix; (где матрица - просто переменная Qmatrix4x4), и тогда m_program->setUniformValue(m_matrixUniform, m_matrix) метод не работает.

На мой взгляд, у меня есть некоторые проблемы либо с обновлением виджета (я просто вызываю update ()), либо со всей логикой шейдера.Спасибо!

//Here is glView.h
#ifndef GLVIEW_H
#define GLVIEW_H
#include <QtOpenGL>
#include <QGLWidget>
#include <QOpenGLWidget>

#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QMouseEvent>

//Class for drawing triangles
class glView : public QOpenGLWidget, public QOpenGLFunctions
{
public:
    glView(float left, float right, float bot, float top, float minz, float maxz)
        : QOpenGLWidget(), QOpenGLFunctions(), f_left(left), f_right(right), f_bot(bot), f_top(top), f_minz(minz), f_maxz(maxz)
    {}
    virtual~glView()
    {}
    void initializeGL() override;
    void resizeGL(int w, int h)override;
    void paintGL()override;

    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void keyPressEvent(QKeyEvent* pe) Q_DECL_OVERRIDE;
private:

    struct CFace{
        int v1,v2,v3;
    };

    GLuint m_posAttr;
    GLuint m_colAttr;
    GLuint m_matrixUniform;
    QOpenGLShaderProgram *m_program;
    int m_frame = 0;
    QMatrix4x4 m_matrix;

    QPoint mPrevMousePos;
};

#endif // GLVIEW_H

и cpp

//Here is glView.cpp
#include <qopengl.h>
#include "glView.h"

#include <QtGui/QGuiApplication>
#include <QtGui/QMatrix4x4>
#include <QtGui/QOpenGLShaderProgram>

#include <QMouseEvent>

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix*posAttr;\n"
    "}\n";

static const char *fragmentShaderSource =
    "varying lowp vec4 col;\n"
    "void main() {\n"
    "   gl_FragColor = col;\n"
    "}\n";

//------------------------------------------------------------------------------
void glView::initializeGL()
{   
    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();
    m_posAttr = m_program->attributeLocation("posAttr");
    m_colAttr = m_program->attributeLocation("colAttr");
    m_matrixUniform = m_program->uniformLocation("matrix");
}
//------------------------------------------------------------------------------

void glView::paintGL()
{   
    QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();

    const qreal retinaScale = devicePixelRatio();
    f->glViewport(0, 0, width() * retinaScale, height() * retinaScale);

    f->glClear(GL_COLOR_BUFFER_BIT);
    m_program->bind();

    QMatrix4x4 matrix;
//Here is the problem!
    //matrix.perspective(0.0f, 4.0f/3.0f, 0.1f, 100.0f);
    //matrix.translate(-5, -5, 0);

    //???
    this->m_matrix=matrix;
    m_program->setUniformValue(m_matrixUniform, m_matrix);


    GLfloat vertices[] = {
        0.0f, 0.707f,
        -0.5f, -0.5f,
        0.5f, -0.5f
    };

    GLfloat colors[] = {
        1.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 1.0f
    };

    f->glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
    f->glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);

    f->glEnableVertexAttribArray(0);
    f->glEnableVertexAttribArray(1);

    f->glDrawArrays(GL_TRIANGLES, 0, 3);

    f->glDisableVertexAttribArray(1);
    f->glDisableVertexAttribArray(0);

    m_program->release();

    ++m_frame;
}

void glView::mousePressEvent(QMouseEvent *event)
{
    mPrevMousePos = event->pos();
    QOpenGLWidget::mousePressEvent(event);
}

void glView::mouseMoveEvent(QMouseEvent *event)
{
    auto diff = event->pos() - mPrevMousePos;
    //??
    this->m_matrix.translate(diff.x()/(width()*0.5), -diff.y()/(height()*0.5));

    mPrevMousePos = event->pos();

    //?? m_program->setUniformValue(m_matrixUniform, m_matrix);
    update();
    QOpenGLWidget::mouseMoveEvent(event);
}

void glView::mouseReleaseEvent(QMouseEvent *event)
{

    QOpenGLWidget::mouseReleaseEvent(event);
}

void glView::keyPressEvent(QKeyEvent *pe)
{
    switch (pe->key())
       {
          case Qt::Key_Up:
             this->m_matrix.scale(QVector3D(2.0f,2.0f,1.0f));
          break;

          case Qt::Key_Down:
             this->m_matrix.translate(QVector3D(0,-1,0));
          break;
       }
    update();
    QOpenGLWidget::keyPressEvent(pe); // Передать событие дальше
}

1 Ответ

0 голосов
/ 02 февраля 2019

1-й параметр QMatrix4x4::perspective - это угол вертикального поля в градусах.Если угол равен 0, поле зрения бесконечно мало, это точка.Для примера используйте 90.0 градусов.

Параметр 3d - это расстояние до ближней плоскости, а четвертый параметр - это расстояние до дальней плоскости.Ближняя и дальняя плоскость определяют предел поля зрения.Вся геометрия должна быть в этой области.Таким образом, в вашем случае значение ближайшего равно 0,1 , а дальнее значение равно 100,0 .
Поскольку ось z указывает на область просмотра в области просмотра, вы должны установить перемещение z, которое больше -0,1 и меньше * -100.0.

Поскольку объем вида в перспективной проекции является усеченной (усеченной пирамидой), количество сдвига x nad y в проекции o области просмотра, зависит от глубины (координата z в пространстве) геометрии и угла поля зрения.Во всяком случае (-5, -5) слишком много с этой настройкой и сместит треугольник из вида.Но вы можете использовать (-1, -1), например.

QMatrix4x4 matrix;
matrix.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(-1.0, -1.0, -2.0);

this->m_matrix=matrix;
m_program->setUniformValue(m_matrixUniform, m_matrix);

Обратите внимание, что обычно матрица вида используется для определения точки обзора и взгляда на сцену.
Проекцияматрица определяет проекцию 3-мерной сцены на порт 2-мерного представления.В перспективной проекции матрица проекции описывает отображение из трехмерных точек в мире, которые они видят из камеры-обскуры, в двумерные точки видового экрана.
Матрица вида определяет точку обзора и направление обзора.Матрица модели определяет ориентацию масштаба и положение объекта в сцене (мире).

Матрица проекции вида модели представляет собой конкатенацию матрицы проекции, вида и модели и определяет преобразование формы координат вершины.шаг модели для отсечения пространства:

mvp = projection * view * model

В вашем случае это означает:

QMatrix4x4 projection;
projection.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);

QMatrix4x4 view;
view.translate(0, 0, -2.0);

QMatrix4x4 model = this->m_matrix;

QMatrix4x4 mvp = projection * view * model;
m_program->setUniformValue(m_matrixUniform, mvp);

Но обратите внимание, что при перспективной проекции величина смещения зависит от глубины объекта, который являетсяперетаскивается в область просмотра.

Если объект находится близко к положению глаза, то перемещение в области просмотра приводит к небольшому смещению положения глаза и цели:

Если расстояние от объекта до глаза слишком велико, то перемещение в области просмотра приводит к большому смещению положения глаза и цели:

См. Демонстрационный пример:

В этом случае сумма будет "равна" с поданнойзрения 90градусы и глубина 1:

QMatrix4x4 projection;
projection.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);

QMatrix4x4 view;
view.translate(0, 0, -1.0);

...