我从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)
不会发生任何事情,并且场景不会更新