假设我要使用两个线程渲染一个动画三角形。一个线程操纵顶点,另一个线程管理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
的指针(如果是,则如何?)。这只是一个玩具示例,通常顶点数据可能非常大。谢谢!!============================
更进一步:
现在我的计划是设置信号->信号->插槽机制。
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) ) );
最佳答案
首先使用信号和插槽机制。如果发出的信号带有点的QList,则QList使用implicit sharing,因此仅写时复制。
这是跨线程使用数据的最简单方法,不需要您对锁进行任何处理。如果在某个时候发现它太慢,则可以考虑优化代码以提高速度。
一种优化的可能方法是使用多个QList点,因此您写入一个点,然后继续写入下一个点,同时发出第一个点,以确保您不写入要共享的列表,从而最大程度地减少了写入时复制的机会。
但是,除非您首先遇到问题,否则无需进行优化。