2014-10-22 3 views
0

두 스레드를 사용하여 애니메이션 삼각형을 렌더링하려고한다고 가정 해 봅니다. 한 스레드는 정점을 조작하고 다른 스레드는 QT 창을 관리하고 GL 컨텍스트를 렌더링합니다. 삼각형 정점을 나타내는 멤버 Eigen::Vector3d m_A, m_B, m_C과 정점에서 작동하는 void updateCoordinates() 메서드가있는 클래스 cTriangle 클래스가 있습니다.Q GL 정점 데이터에 대한 스레드 공유 데이터 방법

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를 생성하고 연속 updateCoordinates() 위에 QThread 루프를 개시한다. 또한 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) 
{} 

마지막으로, 내 질문 : 나는에 정점 데이터에 액세스해야 오브젝트 triGLWidget::painGL에서. 그렇게하는 가장 좋은 방법은 무엇입니까? 신호 슬롯 기능 설정? tri의 포인터를 thread-safe 방식으로 전달합니다 (그렇다면 어떻게?). 이것은 단순한 장난감 예제 일뿐 일반적으로 정점 데이터는 매우 클 수 있습니다. 감사!! 더

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

한 단계 :

이 내 계획이 설정되었습니다 신호 -> 신호 -> 슬롯 메카닉을 설정하십시오. 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

신호 및 슬롯 메커니즘을 사용하여 시작하십시오. 점의 QList로 신호를 내보내는 경우 QList는 implicit sharing을 사용하므로 copy-on-write 만됩니다.

이것은 스레드에서 데이터를 사용하는 가장 간단한 방법이며 사용자가 잠금을 처리 할 필요가 없습니다. 어떤 점에서 속도가 너무 느리다면 속도를 향상시키기 위해 코드를 최적화 할 수 있습니다.

하나의 가능한 최적화 방법은 여러 개의 Q 포인트 목록을 사용하여 하나에 쓰고 다음 글쓰기로 이동하면서 첫 번째 글자를 내보내면서 공유중인 목록에 글을 쓰지 않도록합니다. 따라서 쓰기 중 복사 발생 가능성을 최소화합니다.

그러나 처음에는 문제가없는 한 최적화 할 필요가 없습니다.

+0

Thanks @ Merlin069. 내 계획은 이제 신호 -> 신호 -> 슬롯 역학을 설정하도록 설정되었습니다. GLWidget :: glPaint()는 또 다른 신호'cTriangle :: sendVertices (whateverType vertexData) '에 대해'GLWidget :: requestVertices()'신호를 내 보낸 다음 SLOT'GLWidget :: receiveVertices (whateverType vertexData)'에 의해 수신됩니다. 주.cpp,이 신호들을 어떻게 연결합니까? 'GLWidget' 객체에 대한 참조를 얻으려면 어떻게해야합니까? QObject :: connect (???, SIGNAL (requestVertices()), tri, SIGNAL (sendVertices (double arg)))); – user2926577

+0

StackOverflow에서는 한 번에 하나의 질문을 제기하는 것이 바람직합니다. 답변을 수락 할 수 있으면 대답을 수락 할 수 있습니까? "한 걸음 더 나아"섹션을 제거하고 새 질문을 시작하십시오. 이렇게하면 첫 번째 질문 뒤에 숨어지기보다는 두 번째 질문에 대한 가시성을 높일 수 있습니다. – TheDarkKnight

관련 문제