1. 程式人生 > >QOpenGLWidget + QPainter混合程式設計

QOpenGLWidget + QPainter混合程式設計

本示例將一個二維陣列視覺化,且每一個數據點的顏色由它的Z值決定。根據http://blog.csdn.net/dp_huang/article/details/53816805 在呼叫opengl函式時,要使用glEnable(GL_DEPTH_TEST);而使用QPainter之前,要使用glDisable(GL_DEPTH_TEST);

本示例用到了gluLookAt,所以在pro檔案裡要註明 -lGLU32:

#-------------------------------------------------
#
# Project created by QtCreator 2017-11-07T08:43:48
#
#-------------------------------------------------

QT       += widgets opengl

TARGET = wdtJamInfo
TEMPLATE = lib

DEFINES += WDTJAMINFO_LIBRARY

SOURCES += wdtjaminfo.cpp \
    IntEdit.cpp \
    OperationArray2D.cpp \
    wdtjamplot3d.cpp

HEADERS += wdtjaminfo.h\
        wdtjaminfo_global.h \
    IntEdit.h \
    OperationArray2D.h \
    wdtjamplot3d.h

unix {
    target.path = /usr/lib
    INSTALLS += target
}
LIBS += -lopengl32 -lGLU32

FORMS += \
    wdtjaminfo.ui

資料從函式OnLoadData出進入,觸發繪製。

#ifndef WDTJAMPLOT3D_H
#define WDTJAMPLOT3D_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>



class wdtJamPlot3D : public QOpenGLWidget, protected QOpenGLFunctions
{
	Q_OBJECT
public:
	explicit wdtJamPlot3D(QWidget *parent = 0);
    ~wdtJamPlot3D();

        GLfloat		*		m_pVertices;
        GLfloat		*		m_pColor;
        int					m_iVertices;
		int					m_iStartFreq;
		int					m_iEndFreq;
signals:


protected:
    void initializeGL() Q_DECL_OVERRIDE;
    void paintGL() Q_DECL_OVERRIDE;
    void resizeGL(int width, int height) Q_DECL_OVERRIDE;

    void vDrawAxes(int, int, int);
public slots:
    void        OnLoadData(unsigned char *, int iWidth, int iHeight, float fFreqInterval);
};

#endif // WDTJAMPLOT3D_H
#include "wdtjamplot3d.h"
#include <GL/GLU.h>
#include <QPainter>



wdtJamPlot3D::wdtJamPlot3D(QWidget *parent) : QOpenGLWidget(parent)
{
    m_pVertices = NULL;
    m_pColor = NULL;
    m_iVertices = 0;

	m_iStartFreq = 8200;
	m_iEndFreq = 8560;
}

wdtJamPlot3D::~wdtJamPlot3D()
{
    if(m_pVertices)
        delete [] m_pVertices;
    if(m_pColor)
        delete [] m_pColor;
}

void wdtJamPlot3D::initializeGL()
{
    initializeOpenGLFunctions();

    glEnable(GL_CULL_FACE);
}

void wdtJamPlot3D::paintGL()
{
	glEnable(GL_DEPTH_TEST);

    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //glColor4f(0,1,0, 0);
    glPointSize(1.0);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glColorPointer(4, GL_FLOAT, 4 * sizeof(GL_FLOAT), m_pColor);
    glVertexPointer(3, GL_FLOAT, 3 * sizeof(GL_FLOAT), m_pVertices);
    glDrawArrays(GL_POINTS, 0, m_iVertices);
    //glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

	vDrawAxes(360, 360, 256);

	glDisable(GL_DEPTH_TEST);
	QPainter qp;
	qp.begin(this);
	qp.setPen(QColor(0, 255, 0));
	qp.drawText(width()/6, height()/5, QString("255"));
	qp.drawText(width()/12, height()/5 * 2,	QString::fromLocal8Bit("幅度(dB)"));
	qp.drawText(width()/6, height()/5 * 3, QString("0"));

	qp.setPen(QColor(255, 255, 0));
	qp.drawText(width()/6, height()/5 * 3.5, QString("360"));
	qp.drawText(width()/9, height()/5 * 4,	QString::fromLocal8Bit("方位(度)"));
	qp.drawText(width()/3.9, height()/5 * 3.8, QString("0"));

	qp.setPen(QColor(255, 255, 255));
	qp.drawText(width()/2.8, height()/5 * 4, QString().setNum(m_iStartFreq));
	qp.drawText(width()/2, height()/5 * 4,	QString::fromLocal8Bit("頻率(MHz)"));
	qp.drawText(width()/3 * 2.4, height()/5 * 4, QString().setNum(m_iEndFreq));

	qp.end();
}

void wdtJamPlot3D::resizeGL(int width, int height)
{
    int side = qMin(width, height);
    glViewport((width - side) / 2, (height - side) / 2, side, side);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-400,400, -400,400, 10, 500);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(100, -100, 200, 180,180,128, 0,0,1);
}


void wdtJamPlot3D::OnLoadData(unsigned char *pData, int iWidth, int iHeight, float fFreqInterval)
{
    if(m_pVertices)
        delete [] m_pVertices;
    if(m_pColor)
        delete [] m_pColor;

    m_iVertices = iWidth * iHeight;
    m_pVertices = new GLfloat[m_iVertices * 3];
    m_pColor = new GLfloat[m_iVertices * 4];


    for(int x = 0; x < iWidth; x++)
    {
        for(int y = 0; y < iHeight; y++)
        {
            GLfloat fZ = pData[y * iWidth + x];
            m_pVertices[iWidth * y * 3 + x * 3] = 360.0 * x / iWidth;
            m_pVertices[iWidth * y * 3 + x * 3 + 1] = 360.0 * y / iHeight;
            m_pVertices[iWidth * y * 3 + x * 3 + 2] = fZ * 1.5;

            m_pColor[iWidth * y * 4 + x * 4] = (255 - fZ)/255.0;
            m_pColor[iWidth * y * 4 + x * 4 + 1] = 0;
            m_pColor[iWidth * y * 4 + x * 4 + 2] = fZ/255.0;
            m_pColor[iWidth * y * 4 + x * 4 + 3] = 0;
        }
    }

	m_iStartFreq = 8200;
	m_iEndFreq = m_iStartFreq + fFreqInterval * (iWidth - 1);
	update();
}

void wdtJamPlot3D::vDrawAxes(int iFreqLength, int iAngleLength, int iAmpLength)
{
	//GLfloat arrPnts[18] = {0, 0, 0, 360, 0, 0, 0, 0, 0, 0, 360, 0, 0, 360, 0, 0, 360, 256};
	glPointSize(3.0);
// 	glEnableClientState(GL_VERTEX_ARRAY);
// 	glEnableClientState(GL_COLOR_ARRAY);
// 	glVertexPointer(3, GL_FLOAT, 3 * sizeof(GL_FLOAT), arrPnts);
// 	glDrawArrays(GL_LINE, 0, 2);
// 	glDrawArrays(GL_LINE, 6, 2);
//  	glDrawArrays(GL_LINE, 12, 2);
// 	
// 	glDisableClientState(GL_VERTEX_ARRAY);
// 	glDisableClientState(GL_COLOR_ARRAY);
	glBegin(GL_LINES);
	glColor4f(1.0, 1.0, 1.0, 0);
	glVertex3f(0,0,0);
	glVertex3f(360, 0, 0);
	glColor4f(1.0, 1.0, 0.0, 0);
	glVertex3f(0,0,0);
	glVertex3f(0, 360, 0);
	glColor4f(0.0, 1.0, 0.0, 0);
	glVertex3f(0,360,384);
	glVertex3f(0, 360, 0);
	glEnd();
}

效果: