03.ピックOpenGLレンダラクラスを作る



ピッキング(要素選択)に関する処理を担うピックOpenGLレンダラクラスを、トラックOpenGLレンダラクラスの派生クラスとして作成します。

解説

OpenGLにおける、ピック処理は、古くは、「セレクション」と呼ばれる、セレクションモード(glRenderMode(GL_SELECT))と、関連するルーチン(glSelectBuffer関数、glPushName関数、等)、を使用して、実現しました。

現在においても「セレクション」は使用可能ですが、「セレクション」の使用は推奨されていません。「セレクション」は、OpenGL3で、非推奨となりました。
また、最近のグラフィックボードの中には、「セレクション」について、ハードウェア・アクセラレーション(ハードウェア実装による実行速度向上)の効果が低いものも多くあるようです。

以上から、本「モデルビューワを作る」では、ピックを実現する方法として、「セレクション」ではなく、「オフスクリーンレンダリング」と呼ばれる方法を採用します。
「オフスクリーン」すなわち、(スクリーン上ではなく)メモリ上に描画します。モデルを表示用の色で描画するのではなく、それぞれの要素を識別する色で描画します。描画後、ピックしたピクセルの色を読み込み、ピクセルの色からピックした要素を識別します。

「オフスクリーンレンダリング」の実現方法として、「フレームバッファー」を使用します。
「フレームバッファー」は、OpenGLの拡張機能なので、OpenGLの拡張機能を使えるようにする必要があります。

プロジェクトを開く

02.で作成したモデルビューワプロジェクトを開きます。

OpenGL拡張機能の導入

OpenGL拡張機能の導入の方法

OpenGLの拡張機能を使えるようにするための方法としては、「GLEW」を利用する方法があります。
シェーダー機能を使用する場合など、多くの拡張機能の関数を使用する場合は、「GLEW」を利用するのが楽ですが、
この「モデルビューワを作る」では、全体で、OpenGLの拡張機能を3機能(FrameBuffer、RenderBuffer、VertexBuffer)、関数にして14個程の関数しか使用しないので、「GLEW」を利用する方法ではなく、よりプリミティブ(根源的)な方法である、「glext.hとwglGetProcAddress()」を利用する方法で、OpenGLの拡張機能を使えるようにします。

「GLEW」を利用する方法と、「glext.hとwglGetProcAddress()」を利用する方法とで、OpenGL機能拡張の導入の仕方は異なりますが、拡張機能の使い方は変わりません。

glext.hファイルのダウンロードと設置

Khronos OpenGL® Registry - The Khronos Group Inc」にアクセスし、
「API and Extension Header Files」の項から、
「<GL/glext.h>」と「<KHR/khrplatform.h>」を、「右クリック > 名前を付けて保存」により、
「glext.h」と「khrplatform.h」をダウンロードします。

glext.h ファイルを設置する場所を調べます。
VisualStudioにて、OpenGLRendererBase.hを表示します。

マウスカーソルを「<gl\gl.h>」の上に置き、「右クリック > ドキュメント <gl\gl.h> を開く」で、「gl.h」を開きます。
マウスカーソルを「GL.h」タブの上に置くと、「gl.h」のフルパスが表示されます。
(例えば、「C:\Program Files (x86)\Windows Kits\8.1\Include\um\gl\gl.h」と表示されます。)

「gl.h」のあるフォルダにダウンロードした「glext.h」を設置し、
「gl.h」のあるフォルダの親フォルダ(「gl」フォルダのあるフォルダ)に「KHR」フォルダを作成し、作成した「KHR」フォルダに、ダウンロードした「khrplatform.h」を設置します。
(例えば、「C:\Program Files (x86)\Windows Kits\8.1\Include\um\gl\」に「glext.h」ファイルを設置し、
 「C:\Program Files (x86)\Windows Kits\8.1\Include\um\」に「KHR」フォルダを作成し、
 「C:\Program Files (x86)\Windows Kits\8.1\Include\um\KHR」に「khrplatform.h」を設置します。)

glext.hの設置例


khrplatform.hの設置例

wglGetProcAddress()による関数アドレスの取得

「メニュー/プロジェクト/新しい項目の追加」で
「OpenGLExtFuncs.h」
「OpenGLExtFuncs.cpp」
という2つのファイルを作成します。

それぞれ、内容を以下のようにします。

OpenGLExtFuncs.h


OpenGLExtFuncs.cpp


ビルドし、エラー、警告がないことを確認します。

OpenGL拡張機能を使えるようにするためのヘッダーファイルのインクルード

OpenGLRendererBase.h に以下のOpenGL拡張機能を使えるようにするためのヘッダーファイルのインクルードを追加します。
#include "OpenGLExtFuncs.h"



ビルドし、エラー、警告がないことを確認します。

OpenGL初期化処理の編集

OpenGLRendererBase.cpp にOpenGL初期化処理に、OpenGL拡張機能をつけるようにするための初期化処理の呼び出しを追加します。



ビルドし、エラー、警告がないことを確認します。

ピックOpenGLレンダラクラスの作成

「メニュー/プロジェクト/クラスの追加」でクラス名「COpenGLRendererPick」のクラスを作成します。

テンプレート:C++ クラス
で追加ボタンを押します。

クラス名:COpenGLRendererPick
基底クラス:COpenGLRendererTrack
で完了ボタンを押します。

ビルドし、エラー、警告がないことを確認します。

メンバ変数、メンバ関数の宣言の追加

OpenGLRendererPick.h のピックOpenGLレンダラクラス定義の前に
名前列の大きさの定義
列挙型ERENDERMODEの定義
を追加します。
OpenGLRendererPick.h のピックOpenGLレンダラクラス定義に
メンバ変数、メンバ関数の宣言
を追加します。



ビルドし、エラー、警告がないことを確認します。

メンバ変数の初期化

OpenGLRendererPick.cpp のピックOpenGLレンダラクラスのコンストラクタにメンバ変数の初期化を追加します。



ビルドし、エラー、警告がないことを確認します。

フレームバッファの構築、破棄

OpenGLRendererPick.cpp にフレームバッファの構築、破棄にに関するメンバ関数の定義を追加します。



OpenGLRendererBase.h のベースOpenGLレンダラクラスのメンバ関数
UninitializeOpenGL
をvirtual関数とします。



ビルドし、エラー、警告がないことを確認します。

サイズ変更処理の追加、編集

ピックOpenGLレンダラクラスにサイズ変更処理の定義を追加します。

フレームバッファの構築処理関数の呼び出しを追加します。



OpenGLRendererBase.h のベースOpenGLレンダラクラスのメンバ関数
ChangeSize
をvirtual関数とします。



ビルドし、エラー、警告がないことを確認します。

RenderScene関数のオーバーライド

ベースOpenGLレンダラクラスの描画処理は要素ピックを考慮していません。
ピックOpenGLレンダラクラスに要素ピックを考慮した描画処理 RenderScene関数 をオーバーライドします。

OpenGLRendererPick.cpp の末尾にRenderScene関数の定義を追加します。さらにRenderScene関数で呼び出されるメンバ関数RenderModel関数の定義を追加します。



OpenGLRendererBase.h のベースOpenGLレンダラクラスのメンバ関数
RenderScene
をprotected関数、さらにvirtual関数とします。



ビルドし、エラー、警告がないことを確認します。

DoPicking関数の追加、編集

OpenGLRendererPick.cpp の末尾に要素選択操作に関するメンバ関数の定義を追加します。



ビルドし、エラー、警告がないことを確認します。

レンダラオブジェクトのクラスの変更

ModelViewer.cpp の
#include "OpenGLRendererTrack.h"

#include "OpenGLRendererPick.h"
に、
COpenGLRendererTrack glrenderer;

COpenGLRendererPick glrenderer;
に変更します。



ビルドし、エラー、警告がないことを確認します。

マウス操作イベントハンドラの追加、編集

ModelViewer.cpp の WndProc関数に、以下のマウス操作ウィンドウメッセージ処理を追加します。

ウィンドウメッセージ名
WM_RBUTTONUP

ウィンドウズメッセージにレンダラメンバ関数の呼び出しを追加します。



ビルドし、エラー、警告がないことを確認します。

実行

右クリックにより要素をピックできること
点をピックすると、ピックした点の色がピンク色になり点の大きさが少し大きくなること
線をピックすると、ピックした線の色が水色になり線の太さが少し太くなること
面をピックすると、ピックした面の色が黄色になること
を確認します。

実行結果

ダウンロード

ソースファイルダウンロード ( ModelViewerOpenGLWinAPI2015_03_pick.zip )

関連ページ

前項目:02.トラックOpenGLレンダラクラスを作る

次項目:04.モデルビューワレンダラクラスを作る