OpenGLUT + Qt の非同期での実行について

OpenGLUTのWINDOWとQtのWigetを共存するには、普通に行うとmain関数からQtのWidgetとかGLUTのWindowを出すと、早く呼ばれたどちらかのWindowオブジェクトが表示され、後に呼ばれるもう一つのWindowオブジェクトが表示されません。

また、Qtのmainwindow.cppのコンストラクタからGLUTのWindowを呼んでも同じです。

理由は、メッセージループの話で、どちらも内部でＵＩイベント監視用の無限ループを作っているので、そこのルーチンに入り、もう一つのウィンドウが呼ばれないということになると考えられます。

そこで、Qthreadを使い、非同期で呼ぶソースを添付します。
今回のソースはQthreadを使ってファイアー・アンド・フォーゲットなっているので、アプリがクローズした場合のスレッドを止める処理を考えなければならない。



## Mainwindow

mainwindow.h
``` c
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include "openglut_uitherad.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
    openglut_uiTherad *myth;

public:

    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
   private:
    Ui::MainWindow *ui;
    void createOpenGLUTWinThread();
};
``` 
mainwindow.cpp
``` c

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "./ui_mainwindow.h"


void MainWindow::createOpenGLUTWinThread()
{
    this->myth = new openglut_uiTherad();
    this->myth->moveToThread(myth);
    this->myth->start();
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    //MultithreadでGLUTのWiNDOWを生成する
    createOpenGLUTWinThread();

    ui->setupUi(this);

}

MainWindow::~MainWindow()
{

    this->myth->quit();
    this->myth->exit();

    delete ui;
}

``` 


## openGLUT_UI
openglut_ui.h
``` c
#ifndef OPENGLUT_UI_H
#define OPENGLUT_UI_H

#include <GL/glut.h>
#include <GL/freeglut.h>

#include <QDebug>


class openGLUT_UI : public QObject
{

public:
    openGLUT_UI();

public:

    static void initialOpenGLUT(int argc, char *argv[]);
    static void dispCallback();
    static void resizeCallback(int w, int h);
    static void mouseCallback(int button, int state, int x, int y);

};

#endif // OPENGLUT_UI_H


```
openglut_ui.cpp
``` c
#include "openglut_ui.h"


openGLUT_UI::openGLUT_UI()
{



}

void openGLUT_UI::initialOpenGLUT(int argc, char *argv[])
{
    glutInit(&argc,argv);
    glutCreateWindow("window");
    glutDisplayFunc(openGLUT_UI::dispCallback);

    glutReshapeFunc(openGLUT_UI::resizeCallback);
    glutMouseFunc(openGLUT_UI::mouseCallback);

    glutMainLoop();

}

void openGLUT_UI::dispCallback()
{

    glClear(GL_COLOR_BUFFER_BIT);


    //SET light-gray color
    glClearColor(211.0f/255.0f, 211.0f/255.0f, 211.0f/255.0f, 1.0f);

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

    glFlush();

}

void openGLUT_UI::resizeCallback(int w, int h)
{

    /* ウィンドウ全体をビューポートにする */
    glViewport(0, 0, w, h);

    /* 変換行列の初期化 */
    glLoadIdentity();

    /* スクリーン上の表示領域をビューポートの大きさに比例させる */
    glOrtho(-w / 100, w / 100, -h / 100, h / 100, -1.0, 1.0);

}

void openGLUT_UI::mouseCallback(int button, int state, int x, int y)
{
    switch (button) {
      case GLUT_LEFT_BUTTON:
        qDebug("left");
        break;
      case GLUT_MIDDLE_BUTTON:
        qDebug("middle");
        break;
      case GLUT_RIGHT_BUTTON:
        qDebug("right");
        break;
      default:
        break;
    }
}
```


## openglut_uiTherad

openglut_uiTherad.h
``` c
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>

#include "openglut_ui.h"

class openglut_uiTherad : public QThread
{
    Q_OBJECT
public:
    explicit openglut_uiTherad(QObject *parent = nullptr);

protected:
    void run();

signals:

public slots:
};

#endif // MYTHREAD_H

```

openglut_uiTherad.cpp
``` c
#include "openglut_uitherad.h"

openglut_uiTherad::openglut_uiTherad(QObject *parent) : QThread(parent)
{

}

void openglut_uiTherad::run()
{
     openGLUT_UI::initialOpenGLUT(0,nullptr);
}
```