Qt GUIで3Dプリミティブの境界ボックスを描画する:QOpenGLExtraFunctions::glPrimitiveBoundingBox()徹底解説
QOpenGLExtraFunctions::glPrimitiveBoundingBox()
は、OpenGL ES 3.x、OpenGL 3.x、またはOpenGL 4.xコンテキストで使用できる関数で、3Dプリミティブの境界ボックスを描画するために使用されます。境界ボックスは、プリミティブを完全に囲む最小と最大の立方体です。
関数詳細
void QOpenGLExtraFunctions::glPrimitiveBoundingBox(
GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW,
GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW
);
maxW
: 境界ボックスの最大幅maxX
,maxY
,maxZ
: 境界ボックスの最大座標(x, y, z)minW
: 境界ボックスの最小幅minX
,minY
,minZ
: 境界ボックスの最小座標(x, y, z)
使い方
QOpenGLExtraFunctions
インスタンスを取得します。initializeOpenGLFunctions()
を呼び出して、コンテキストを指定します。glPrimitiveBoundingBox()
を呼び出して、境界ボックスの座標と幅を指定します。
QOpenGLExtraFunctions glFuncs(context);
glFuncs.initializeOpenGLFunctions();
// プリミティブを描画
...
// 境界ボックスを描画
glFuncs.glPrimitiveBoundingBox(-1.0f, -1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f);
- 境界ボックスは、デバッグや視覚化に役立ちます。
- 境界ボックスのスタイルは、
glLineWidth()
やglPolygonMode()
などの関数で設定できます。 - 境界ボックスの色は、
glColorMaterial()
やglMaterial()
などの関数で設定できます。
- OpenGL ES、OpenGL 3.x、OpenGL 4.xの詳細については、OpenGL仕様を参照してください。
- この説明は、Qt GUI 6.7.1を対象としています。他のバージョンでは、関数の名前や引数が異なる場合があります。
#include <QCoreApplication>
#include <QOpenGLWidget>
class MyWidget : public QOpenGLWidget {
public:
MyWidget() {
setFixedSize(200, 200);
}
protected:
void paintGL() override {
QPainter painter;
painter.begin(this);
// OpenGLの設定
glViewport(0, 0, width(), height());
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
// 立方体の描画
glBegin(GL_QUADS);
glVertex3f(-0.5f, -0.5f, -0.5f);
glVertex3f( 0.5f, -0.5f, -0.5f);
glVertex3f( 0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, 0.5f, -0.5f);
glVertex3f(-0.5f, -0.5f, 0.5f);
glVertex3f( 0.5f, -0.5f, 0.5f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glEnd();
// 境界ボックスの描画
QOpenGLExtraFunctions glFuncs(context());
glFuncs.initializeOpenGLFunctions();
glFuncs.glPrimitiveBoundingBox(-1.0f, -1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f);
// 赤色で境界ボックスを描画
glColor3f(1.0f, 0.0f, 0.0f);
painter.end();
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
このコードは、200x200ピクセルのウィンドウに赤い立方体を表示し、その境界ボックスを赤色で描画します。
例2: 円柱の境界ボックスを描画
#include <QCoreApplication>
#include <QOpenGLWidget>
class MyWidget : public QOpenGLWidget {
public:
MyWidget() {
setFixedSize(200, 200);
}
protected:
void paintGL() override {
QPainter painter;
painter.begin(this);
// OpenGLの設定
glViewport(0, 0, width(), height());
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
// 円柱の描画
GLUquadric *quadric = gluNewQuadric();
gluQuadricNormals(quadric, GLU_SMOOTH);
gluCylinder(quadric, 0.5f, 0.5f, 2.0f);
gluDeleteQuadric(quadric);
// 境界ボックスの描画
QOpenGLExtraFunctions glFuncs(context());
glFuncs.initializeOpenGLFunctions();
glFuncs.glPrimitiveBoundingBox(-0.5f, -1.0f, -0.5f, 0.0f,
0.5f, 1.0f, 0.5f, 0.0f);
// 緑色で境界ボックスを描画
glColor3f(0.0f, 1.0f, 0.0f);
painter.end();
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
このコードは、200x200ピクセルのウィンドウに緑色の円柱を表示し、その境界ボックスを緑色で描画します。
- 上記のコードは、Qt Creator 6.4.2とQt 6.7.1
QOpenGLExtraFunctions::glPrimitiveBoundingBox()
は、3Dプリミティブの境界ボックスを描画するための便利な関数ですが、いくつかの代替方法があります。
代替方法
gluBox()
関数を使用する:- 古典的なOpenGLライブラリであるGLUTの
gluBox()
関数を使用して、境界ボックスを描画できます。 gluBox()
は、glPrimitiveBoundingBox()
よりもシンプルで使いやすいですが、OpenGL ES 2.0以降ではサポートされていません。- GLUTライブラリを別途インストールする必要があります。
- 古典的なOpenGLライブラリであるGLUTの
カスタムシェーダーを使用する:
- カスタムシェーダーを使用して、境界ボックスを描画できます。
- カスタムシェーダーは、より柔軟性と制御性がありますが、複雑でコード量が多くなります。
- シェーダープログラミングの知識が必要です。
glPolygonMode()
とglColorMaterial()
を使用する:glPolygonMode()
とglColorMaterial()
を使用して、プリミティブをワイヤーフレームモードで描画し、境界ボックスの色を設定できます。- この方法は、単純な境界ボックスを描画する場合に役立ちますが、複雑な形状には適していません。
各方法の比較
方法 | 利点 | 欠点 |
---|---|---|
gluBox() | シンプルで使いやすい | OpenGL ES 2.0以降ではサポートされていない |
カスタムシェーダー | 柔軟性と制御性が高い | 複雑でコード量が多い |
glPolygonMode() とglColorMaterial() | シンプル | 複雑な形状には適していない |
例
例1: gluBox()関数を使用する
#include <GL/glut.h>
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// プリミティブを描画
...
// 境界ボックスを描画
gluBox(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f);
glutSwapBuffers();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(200, 200);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL Example");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
例2: カスタムシェーダーを使用する
#include <QCoreApplication>
#include <QOpenGLWidget>
class MyWidget : public QOpenGLWidget {
public:
MyWidget() {
setFixedSize(200, 200);
}
protected:
void initializeGL() override {
// シェーダープログラムの初期化
...
}
void paintGL() override {
QPainter painter;
painter.begin(this);
// OpenGLの設定
glViewport(0, 0, width(), height());
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
// プリミティブを描画
...
// カスタムシェーダーを使用して境界ボックスを描画
glUseProgram(boundingBoxProgram);
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix.data());
glUniformMatrix4fv(viewLocation, 1, GL_FALSE, viewMatrix.data());
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, modelMatrix.data());
glDrawArrays(GL_QUADS, 0, 4);
painter.end();
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
#include <QCoreApplication>
#include <QOpenGLWidget>
class MyWidget : public QOpenGLWidget {
public:
MyWidget() {
setFixedSize(200, 200);
}
protected:
void paintGL() override {
QPainter painter;
painter.begin(this);
// OpenGLの設定