Как исправить QTGLWidget, используя QTimer, чтобы уменьшить время рендеринга?

В настоящее время я использую QtOpenGL для моей программы. Моя программа строит точки в трехмерном пространстве. Эти точки могут быть любым числом от одной до нескольких тысяч. Я использую функцию glusphere для рисования сферы для представления каждой точки. При этом создается каждый кадр, и мне нужно отображать каждый кадр как анимацию, используя QTimer. Эта анимация должна контролироваться fps. Например, если fps=30, я бы поставил t=1000/30 для setInterval(t) QTimer. Если fps = 10 или 30, я обнаружил, что fps не сильно меняет мою программу. Я искал проблему, устанавливая fps в 0, и наблюдал, сколько времени занимает рендеринг, используя setInterval(0). Ниже приведены результаты:

n = количество сфер

когда n=10: 28 мс => около 30 мс

когда n=100: 87мс => около 90мс

когда n=150: 137 мс => около 140 мс

когда n=1000: 598 мс => около 600 мс => 0,6 с

Из результатов, приведенных выше, время рендеринга каждого кадра линейно увеличивается с количеством сфер. Следующее является частью моего кода:

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{
    setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer));
    scale=1.0;
    rot_x=0;
    rot_y=0;
    rot_z=0;
    trans_x=0;
    trans_y=0;
    trans_z=0;
    isloaded=false;
    isplayed=false;
    currentFrame=1;
    sphereNum=1;
    myTimer=new QTimer(this);
    //fps=60;
    myTimer->setInterval(0);

    //myTimer->setInterval();
    connect(myTimer, SIGNAL(timeout()), this, SLOT(timerEvent()));
}

void GLWidget::initializeGL()
{
    qglClearColor(QColor(Qt::black));
    glEnable(GL_DEPTH_TEST);
    srand((unsigned)time(NULL));
    //QGLFormat::setDoubleBuffer(true);
    //qDebug() << "initGL context: " << this->context();
}

void GLWidget::timerEvent()
{
    static QTime current_time, last_time;
    int elapsed_time;
    last_time=current_time;
    current_time=QTime::currentTime();
    elapsed_time=(current_time.second()*1000 + current_time.msec())-(last_time.second()*1000 + last_time.msec());
    //qDebug() << "Timer elapsed time: " << elapsed_time;
    if(isloaded && isplayed) {
        if(currentFrame<markerData.frameSize) currentFrame++;
        makeCurrent();
        updateGL();
    }
    if(currentFrame==markerData.frameSize) {
        isplayed=false;
        myTimer->stop();
        currentFrame=1;
    }
}

void GLWidget::drawSphere(GLfloat x, GLfloat y, GLfloat z, GLfloat radius)
{
    qglColor(Qt::yellow);
    glPushMatrix();
    glTranslatef(x, y, z);
    gluSphere(p, radius, 10, 10);
    //gluCylinder(p, 10, 10, 10, 4, 4);
    glPopMatrix();
}

void GLWidget::drawMarkers() {
    int markerIndex;
    glPushMatrix();
    /*for(int i=0; i<markerData.rowSize; i++) {
        markerIndex=(currentFrame-1)*markerData.rowSize+i;
        //qDebug() << markerIndex;
        drawSphere(markerData.markerSet[markerIndex].x, markerData.markerSet[markerIndex].y, markerData.markerSet[markerIndex].z, 10);
    }*/
    for(int i=0; i<sphereNum; i++) {
        markerIndex=rand()%1000;
        drawSphere(markerIndex, markerIndex, markerIndex, 10);
    }
    glPopMatrix();
}

void GLWidget::drawText(double x, double y, double z, QString txt)
{
    glDisable(GL_DEPTH_TEST);
    qglColor(Qt::white);
    renderText(x, y, z, txt, QFont("Arial", 12, QFont::Bold, false) );
    glEnable(GL_DEPTH_TEST);
}

void GLWidget::paintGL()
{
    static QTime current_time, last_time;
    int elapsed_time;
    float paint_fps;
    //if file data is loaded
    if(isloaded)
    {
        //calculate elapsed time drown 1 frame per second
        //elapsed time is millisecond
        last_time=current_time;
        current_time=QTime::currentTime();
        elapsed_time=(current_time.second()*1000 + current_time.msec())-(last_time.second()*1000 + last_time.msec());
        paint_fps=1000/elapsed_time;
        //qDebug() << "elapsed time: " << elapsed_time << "  fps: " << paint_fps;

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f,0.0f,-20.0f);
        glRotatef(30.0, 0.0, 1.0, 0.0);
        glRotatef(15.0, 1.0, 0.0, 0.0);
        glRotatef(rot_x, 1.0, 0.0, 0.0);
        glRotatef(rot_y, 0.0, 1.0, 0.0);
        glRotatef(rot_z, 0.0, 0.0, 1.0);
        glScalef(scale, scale, scale);
        glTranslatef(trans_x, trans_y, trans_z);

        //draw elapsed time(ms)
        glPushMatrix();
        drawText(100, -300, 100, QString::number(elapsed_time) + "ms"); 
        glPopMatrix();

        //draw 3-axis
        glBegin(GL_LINES);
        qglColor(Qt::red);
        glVertex3f(0, 0, 0);
        glVertex3f(3000, 0, 0);
        glEnd();
        glBegin(GL_LINES);
        qglColor(Qt::green);
        glVertex3f(0, 0, 0);
        glVertex3f(0, 3000, 0);
        glEnd();
        glBegin(GL_LINES);
        qglColor(Qt::blue);
        glVertex3f(0, 0, 0);
        glVertex3f(0, 0, 3000);
        glEnd();

        //draw spheres
        p=gluNewQuadric();
        drawMarkers();
        gluDeleteQuadric(p);

        //swapBuffers
        if(doubleBuffer()) {
            swapBuffers();
            makeCurrent();
        }
    }
}

Чтобы уточнить:

  • Время рендеринга для каждого кадра меняется в зависимости от количества сфер.
  • Количество сфер не должно менять время рендеринга
  • Хотя он рисует 1000 сфер, он тратит полсекунды
  • Как вы думаете, проблема в использовании Glusphere?
  • Если есть другой способ нарисовать сферу, возможно ли сделать это более 100 кадров в секунду?

Может кто-нибудь объяснить, где узкое место, которое создает этот медленный рендеринг?

0 ответов

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