有没有办法刷新QGraphicsScene的某些部分

时间:2020-07-27 06:07:20

标签: qt opengl qgraphicsscene

我从QGraphicsScene继承了myScene类,以模拟简单的PPI显示。为了提高效率,我想随时更新场景的一部分,而不是整个(bool allRefresh = false;),但是在这种情况下,场景将被清除。我需要类似bool allRefresh = true;的命令。

#ifndef MYSCENE_H
#define MYSCENE_H

#include <QDebug>
#include <QtWidgets>
#include <QtOpenGL>
#include <QGraphicsScene>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#define MAX_ANGLE 8192
#define _PI 3.1415926535897932384626433832795
#define _2PI 6.2831853071//(2*_PI)
#include <QTimer>


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 =  posAttr;\n"
        "}\n";

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

class myScene : public QGraphicsScene
{
    Q_OBJECT
private:
    double m_dWidth;
    GLuint m_posAttr;
    GLuint m_colAttr;
    GLuint m_matrixUniform;
    GLfloat *vertices2d;
    GLfloat *colors2d;
    int m_frame;
    int pointCounts;
    int ImaxR;
    QTimer *mTimer;
    int curAngle = MAX_ANGLE;
    int AngleDiff = 5;


    QOpenGLShaderProgram *m_program;
public:

    myScene(int Width,QWidget *parent)
        : QGraphicsScene(parent),
          m_dWidth(Width)
    {
        ImaxR = m_dWidth/2;
        setItemIndexMethod(QGraphicsScene::NoIndex);
        setBackgroundBrush(QBrush(Qt::black, Qt::SolidPattern));
    }


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

        static bool first = true;
        if(first)
        {
            first = false;
            vertices2d = new GLfloat[ImaxR*MAX_ANGLE*2];
            memset(vertices2d,0,ImaxR*MAX_ANGLE*2*sizeof(GLfloat));

            colors2d = new GLfloat[ImaxR*MAX_ANGLE*3];
            memset(colors2d ,0,ImaxR*MAX_ANGLE*3*sizeof(GLfloat));

            GLfloat *testX = new GLfloat[ImaxR*MAX_ANGLE];
            GLfloat *testY = new GLfloat[ImaxR*MAX_ANGLE];

            int index =0;
            int MaxTeta = MAX_ANGLE;
            for (int i=0;i<MAX_ANGLE;i++)
            {
                int rot = (i+(MAX_ANGLE/4))%MAX_ANGLE;
                float teta = float(rot*_2PI) / float(MaxTeta);
                for (int j=0;j<ImaxR;j++)
                {
                    float x=j*cos(teta);
                    float y=j*sin(teta);
                    testX[index] = x/ImaxR;
                    testY[index] = y/ImaxR;
                    index++;
                }
            }

            for (int i = 0; i < index; i++)
            {
                vertices2d[i*2+0] = testX[i];
                vertices2d[i*2+1] = testY[i];
            }
            pointCounts = index;
            mTimer = new QTimer(this);
            mTimer->setInterval(10);
            connect(mTimer, SIGNAL(timeout()), this, SLOT(renderNow()));
           mTimer->start();
            glViewport(0, 0, ImaxR , ImaxR );
        }
    }


    void renderScope()
    {

        bool b =  m_program->bind();
        int offset = curAngle * ImaxR;
        for (int i = offset; (i < offset+(ImaxR*AngleDiff)) && (i<pointCounts) ; i++)
        {
            colors2d[i*3+0] = (float)((rand())%5) /10;
            colors2d[i*3+1] = 0;
            colors2d[i*3+2] = 0;
        }

        (curAngle-=AngleDiff);
        if(curAngle <0 )
            curAngle = MAX_ANGLE;

        GLfloat *vertices = (GLfloat *)vertices2d;
        GLfloat *colors = (GLfloat *)colors2d;


        m_program->enableAttributeArray(m_posAttr);
        m_program->setAttributeArray(m_posAttr,GL_FLOAT, vertices,2);


        m_program->enableAttributeArray(m_colAttr);
        m_program->setAttributeArray(m_colAttr,GL_FLOAT, colors,3);

        bool allRefresh = true;
        if(!allRefresh)
        {
            if( (offset + (ImaxR*AngleDiff) < pointCounts ) && offset >= 0)
            {
                glDrawArrays(GL_POINTS, offset, ImaxR*AngleDiff);

            }
            else
            {
                glDrawArrays(GL_POINTS, offset, pointCounts-offset);
            }
        }
        else
        {
            glDrawArrays(GL_POINTS, 0, pointCounts);
        }


        m_program->release();

    }

    virtual void drawBackground(QPainter *painter, const QRectF &rect) Q_DECL_OVERRIDE
    {
        //QGraphicsScene::drawBackground(painter,rect);
        painter->beginNativePainting();
        renderScope();
        painter->endNativePainting();

        return ;
    }

public slots:
    void renderNow()
    {
        update();
    }

};
#endif // MYSCENE_H

此外,使用QGraphicsScene::update(qreal x, qreal y, qreal w, qreal h)不会发生任何事情,并且场景不会更新

0 个答案:

没有答案