C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

QtCreator-2.5.0 + QtOpenGL + GLUT ==> teapot

(いちおう)エディターたるVimから、IDEたるQtCreatorでの開発を勉強中。先ずはお約束の第一歩、teapotの備忘録。

プロジェクトをQtの雛形から作成

  1. File --> New file or Project (CTRL+N)
  2. Projects: Applications --> Qt Gui Application

以降、仮にプロジェクト名称を"hoge"としたものとして進める。

ウィザードに従い、特に困る事は無く、

  • hoge.pro
  • Headers
    • mainwindow.h
  • Sources
    • main.cpp
    • mainwindow.cpp
  • Forms
    • mainwindow.ui

が生成される。バージョン管理システムとしてgitを仕込むのもプロジェクト作成時にまとめてできる。

この時点で既にビルド&実行してもフォームが見えるだけのアプリが立派に動作してくれる。

QtOpenGL を組み込む

どうやら Qt で OpenGL を扱う標準的な方法として、 QtOpenGL なるAPIがあるらしい。

プロジェクトに QtOpenGL を使う為の定義を施す。

hoge.pro

.pro はどうやら QtCreator におけるプロジェクトファイル、プロジェクトのソースコード以外のアレコレを定義するファイルらしい。この.proに

QT += opengl

を加える。どうも見るからにMakefile系のスクリプト的な感じで変数を定義しているらしい。この QT なる変数はQt系のライブラリーのリンクを制御したり、UIデザイナーでの挙動に関わっているのではないかと思う。

これでこのプロジェクトでは QGLWidget などの QtOpenGL 周りのライブラリーが使用可能になる。

ついで C++11 を使いたければ、

QMAKE_CXXFLAGS += -std=c++11

も追記しておく。

QGLWidget を実装

  1. File --> New file or Project (CTRL+N)
  2. Files and Classes: C++ --> C++ Class

などして QtOpenGL による Qt の OpenGLWidget (フォーム部品)を実装する。

"gl_widget"なるクラスを QtCreator で作成したとして進める。差し当たり次の様に OGLWidget を継承して gl_widget を実装する。

gl_widget.h
#ifndef GL_WIDGET_H
#define GL_WIDGET_H

#include <QtOpenGL>

class gl_widget: public QGLWidget
{
  Q_OBJECT
public:
  gl_widget(QWidget*);
protected:
  virtual ~gl_widget();
  virtual void initializeGL();
  virtual void resizeGL(int, int);
  virtual void paintGL();
};

#endif // GL_WIDGET_H

Q_OBJECT は Qt 関連品にはとりあえず付けておけば問題無い様だ。今回の本題でも無いので今回はとりあえず付けて置くでスルー。

Qt Note: Q_OBJECT を付けるべきか

includeガードがいつも#pragmaな癖にとかは今回QtCreatorの雛形からできるだけそのままにして居るので気にしないで戴きたい。

gl_widget.cpp
#include "gl_widget.h"

gl_widget::gl_widget(QWidget* p = nullptr)
  :QGLWidget(p)
{}

gl_widget::~gl_widget(){}

void gl_widget::initializeGL(){
  glClearColor(.0, .0, .0, 1.);
}

void gl_widget::resizeGL(int x, int y){
  glViewport(0, 0, x, y);
  glLoadIdentity();
  auto rx = x / 200.;
  auto ry = y / 200.;
  auto z = 1;
  glOrtho(-rx, rx, -ry, ry, -z, z);
}

void gl_widget::paintGL(){
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  //glutWireTeapot(0.5);
}

いつもは .hxx とかしてこの程度なら実装もヘッダーに詰め込む癖にー、とかも気にしないで戴きたい。あとファイル名とか。これらも基本的に今回は QtCreator の生成した雛形そのままです。

initializeGL/resizeGL/paintGL は QGLWidget に定義された仮想関数で、初期化/サイズ変更/描画のタイミングでよしなに呼ばれてくれます。素のGLの各種コールバック"的"なものですね。

paintGLで`// glutWireTeapot(0.5);`がコメントアウトしてありますが、これはまだ GLUT の準備をしていない為に使用できないからです。それでも実行すれば glClearColor で設定した色で glClear により描画タイミング毎に画面がクリアされるので動作は確認できるでしょう。

でもまだビルド&実行しても真っ黒なGLの描画画面は現れません。次にこの実装した Qt のウィジェットをフォームに組み込みます。

mainwindow.ui へ gl_widget を組み込む

mainwindow.ui を QtCreator で開くとソースではなくグラフィカルなUIデザイナーが表示されます。標準ではフォームの表示されている右側にオブジェクトをツリー表示している部分が出ているので、そこで MainWindow の中の centralWidget のコンテキストメニューを開き、 `promote to` しましょう。

Promoted class name に gl_widget と先ほど実装したQtのOpenGLウィジェットを書き込むと、自動的に Header file も gl_widget.h と入力の済んだ状態になります。 Add して Promoted Classes に表示が出たならば、ビルド&実行してみましょう。

f:id:USAGI-WRP:20121209151323p:plain

先ほど実装した gl_widget が無事に動作すると真っ黒でクリアーするだけのGLの小窓が出ます。

GLUT ==> teapot

続いて GLUT を QtCreator のプロジェクトのお作法で準備します。

hoge.pro
LIBS += -lglut

身も蓋もない気がしますが、変数LIBに -lglut とか GCC/clang のライブラリーリンクオプションを加えます。

main.cpp
#include <QApplication>
#include <GL/glut.h>
#include "mainwindow.h"

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

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

`GL/glut.h` のインクルードと `glutInit(&argc, argv)` を追加しました。他は QtCreator で生成した雛形のままです。

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

追加しておきましょう。

gl_widget.cpp
  glutWireTeapot(0.5);

コメントアウトしてあった teapot の描画コードのコメントアウトを外しましょう。

ビルド&実行すると、

f:id:USAGI-WRP:20121209152149p:plain

GLUTお約束の teapot が描画されました (*´ω`*)