用于GL顶点数据的QThread数据共享方法

时间:2014-10-22 06:45:16

标签: c++ multithreading qt

我想说我想用两个线程渲染一个动画三角形。一个线程操纵顶点,另一个线程管理QT窗口并呈现GL上下文。我有一个类cTriangle,成员Eigen::Vector3d m_A, m_B, m_C表示三角形顶点,方法void updateCoordinates()表示顶点。

cTriangle.h:

#ifndef CTRIANGLE_H
#define CTRIANGLE_H

#include <Eigen/Core>
#include <QObject>
#include <vector>

class cTriangle : public QObject
{
    Q_OBJECT

public:
    cTriangle();

public:

    Eigen::Vector3d m_A;
    Eigen::Vector3d m_B;
    Eigen::Vector3d m_C;

public slots:
    void updateCoordinates();

};

#endif // CTRIANGLE_H

cTriangle.cpp:

#include "cTriangle.h"
#include <iostream>

cTriangle::cTriangle()
{
    m_A = Eigen::Vector3d(0.0, 0.0, 0.0);
    m_B = Eigen::Vector3d(0.2, 0.0, 0.0);
    m_C = Eigen::Vector3d(0.0, 0.2, 0.0);
}

void cTriangle::updateCoordinates()
{
    int ctr = 0;
    double t = 0.0;

    while (true)
    {
        std::cout << "cTriangle::updateCoordinates " << ctr << std::endl;
        double offset = 0.3*sin(t);
        m_A = Eigen::Vector3d(offset, 0.0, 0.0);
        t += 0.00001;
        ctr++;
    }
}

驱动程序创建一个新的cTriangle并启动一个QThread,它继续循环updateCoordinates()。我还初始化包含GLWidget的MainWindow。

main.cpp中:

int main(int argc, char *argv[])
{

    cTriangle* tri = new cTriangle();

    QThread* thread = new QThread;
    tri->moveToThread(thread);
    QObject::connect(thread, SIGNAL(started()), tri, SLOT(updateCoordinates()) );
    thread->start();


    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

glwidget.h:

#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
#include "cTriangle.h"

class GLWidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit GLWidget(QWidget *parent = 0);
    void initializeGL();
    void resizeGL(int w, int h);

private:

signals:
    void repaint();

public slots:
    void paintGL();

};

#endif // GLWIDGET_H

glwidget.cpp:

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{


}

void GLWidget::initializeGL()
{
    glClearColor(0.2, 0.2, 0.2, 1);
}
void GLWidget::paintGL()
{
    std::cout << "paintGL " << std::endl;

    // ********************************
    // How do I access Triangle data here??
    // ********************************


    glClear(GL_COLOR_BUFFER_BIT);

    glLoadIdentity();

    glBegin(GL_TRIANGLES);
        glColor3f  (1,0,0);
        glVertex3f (0, -0.5, 0);
        glColor3f  (0,1,0);
        glVertex3f (0.5, -0.5, 0);
        glColor3f  (0,0,1);
        glVertex3f (0.0, 0.5, 0);
    glEnd();

}
void GLWidget::resizeGL(int w, int h)
{}

最后,我的问题是:我需要从tri内访问对象GLWidget::painGL中的顶点数据。这样做的最佳方法是什么?设置信号槽功能?以线程安全的方式传递tri的指针(如果是,如何?)。这只是一个玩具示例,通常顶点数据可能非常大。谢谢!

=============================

更进一步:

我的计划现在设置了信号 - &gt;信号 - &gt;插槽机制。 GLWidget::glPaint()向另一个SIGNAL GLWidget::requestVertices()发出SIGNAL cTriangle::sendVertices(whateverType vertexData),然后由SLOT GLWidget::receiveVertices(whateverType vertexData)收到。在main.cpp中,如何连接这些信号?如何获取对GLWidget对象的引用? QObject::connect( ???, SIGNAL( requestVertices() ), tri, SIGNAL( sendVertices(double arg) ) );

1 个答案:

答案 0 :(得分:1)

首先使用信号和插槽机制。如果发出带有QList点的信号,则QList使用implicit sharing,因此只会写入时复制。

这是跨线程使用数据的最简单方法,并且不需要您对锁进行任何处理。如果在某些时候您发现这个太慢,那么您可以考虑优化代码以提高速度。

一种可能的优化方法是使用多个QList的点,所以你写一个,然后继续写到下一个,同时发出第一个,以确保你不写入列表是共享,从而最大限度地减少了写入时复制的可能性。

但是,除非您首先发现问题,否则无需进行优化。