Как сделать так, чтобы исходная (0,0) координата находилась в верхнем левом углу QGLWIdget?

Я хочу отобразить изображение с помощью QGLWidget, оно отображается неправильно, одна из проблем заключается в том, что исходная координата находится в левом нижнем углу виджета. Я хотел бы знать, как сделать так, чтобы исходная координата находилась слева вверху и отразила ось Y.

вот мой код:

заголовок

#ifndef _GLImageDisplay_H_
#define _GLImageDisplay_H_

#include "stdafx.h"

class GLImageDisplay : public QGLWidget
{
    Q_OBJECT

public:
    GLImageDisplay(QWidget *parent = 0);

    void DisplayImage(QString img);

protected:
    void initializeGL();
    void resizeGL(int w, int h);
    void paintGL();

private:
    QImage svgImage;
    GLubyte* gluImage;
};

#endif

CPP

#include "stdafx.h"
#include "GLImageDisplay.h"

GLImageDisplay::GLImageDisplay(QWidget *parent) : QGLWidget (parent) 
{
}

void GLImageDisplay::DisplayImage(QString img)
{
    svgImage.load(img);
    resize(svgImage.size());

    gluImage = new GLubyte[svgImage.height() * svgImage.width() * 3];
    for (int a = 0; a < svgImage.width(); ++a)  
    {
        for (int b = 0; b < svgImage.height(); ++b) 
        {
            QColor color = svgImage.pixel(a, b);
            gluImage[3 * (a + b * svgImage.width()) + 0] = (GLubyte) color.red();
            gluImage[3 * (a + b * svgImage.width()) + 1] = (GLubyte) color.green();
            gluImage[3 * (a + b * svgImage.width()) + 2] = (GLubyte) color.blue();
        }
    }

    this->setMinimumWidth(svgImage.width());
    this->setMinimumHeight(svgImage.height());
}

void GLImageDisplay::initializeGL() 
{
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}

void GLImageDisplay::resizeGL(int w, int h) 
{
    glViewport(0, 0, svgImage.width(), svgImage.height());

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, svgImage.width(), 0, svgImage.height(), 0, 1);   
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void GLImageDisplay::paintGL() 
{
    glClear(GL_COLOR_BUFFER_BIT);
    glRasterPos2i(0, 0);
    glDrawPixels(svgImage.width(), svgImage.height(), GL_RGB, GL_UNSIGNED_BYTE, gluImage);
}

2 ответа

Решение

Координаты OpenGL начинаются снизу. Чтобы это исправить, вы можете выполнить масштабирование -1 по оси Y в матрице проекции. Смещение связано.

Чтобы это исправить, измените ваш звонок на glOrtho или примените масштабирование + перевод сразу после звонка.

Btw. Вы также можете использовать QPainter и использовать beginNativePainting() везде, где вам действительно нужно GL. QPainter уже будет использовать сам GL и работать очень хорошо.

glDrawPixels это очень неэффективный способ рисования изображения на экране. Вы должны скорее загрузить его в текстуру и нарисовать четырехугольник с ним. (Еще раз, QPainter может сделать это для вас тоже гораздо проще.)

Спасибо, ypnos!

в конце я переворачиваю матрицу проекции gluOrtho2D(0, ширина, высота, 0); и переверните текст координаты.

вот мой код:

#include "stdafx.h"
#include "GLImageDisplay.h"

GLImageDisplay::GLImageDisplay(QWidget *parent) : QGLWidget (parent) 
{
}

void GLImageDisplay::DisplayImage(QString img)
{
    myImage.load(img);

    // calculating power-of-two (pow) size
    int xpow = (int) std::pow(2.0, std::ceil(  std::log10((double)myImage.width())/std::log10(2.0)  )   );
    int ypow = (int) std::pow(2.0, std::ceil(  std::log10((double)myImage.height())/std::log10(2.0)  )   );

    // the texture should be square too
    xpow = std::max(xpow, ypow);
    ypow = xpow;

    // shrink if the size is too big
    if(xpow > 1024) 
    {
        xpow = 1024;
        ypow = 1024;
    }

    // transform the image to square pow size
    scaledImage = myImage.scaled(xpow, ypow, Qt::IgnoreAspectRatio);
    glImage = QGLWidget::convertToGLFormat(scaledImage);

    this->setMinimumWidth(myImage.width());
    this->setMinimumHeight(myImage.height());

    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &imageID);
    glBindTexture( GL_TEXTURE_2D, imageID );
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, scaledImage.width(), scaledImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glDisable(GL_TEXTURE_2D);
}

void GLImageDisplay::initializeGL() 
{
    glClearColor(0.5, 0.5, 0.5, 1.0);
}

void GLImageDisplay::resizeGL(int width, int height) 
{   
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width, height, 0);    // flip the y axis
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void GLImageDisplay::paintGL() 
{
    int width = myImage.width();
    int height = myImage.height();

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1,0,0);
    glBegin(GL_POLYGON);
    glVertex2f(10,10);
    glVertex2f(10,600);
    glVertex2f(300,10);
    glEnd();

    glEnable(GL_TEXTURE_2D);
    glColor3f(1,1,1);
    glBindTexture( GL_TEXTURE_2D, imageID );
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glImage.width(), glImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());

    glBegin(GL_QUADS);

    // text coord is flipped
    glTexCoord2d(0,1); glVertex3d(0,     0,      0);
    glTexCoord2d(1,1); glVertex3d(width, 0,      0);
    glTexCoord2d(1,0); glVertex3d(width, height, 0);
    glTexCoord2d(0,0); glVertex3d(0,     height, 0);

    glEnd();
    glDisable(GL_TEXTURE_2D);
}

но я сталкиваюсь с другой проблемой, когда пытаюсь отобразить большое изображение, где нижняя часть виджета обрезана и отображает черную область. Кажется, что виджет отображается только на высоте моего ЖК-экрана (?) Мне интересно, QGLWidget не может быть легко помещен в QScrollArea (?). Это другая проблема, хотя.

Другие вопросы по тегам