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

(開発環境として「Eclipse」を使用した、古い情報です。
 開発環境として「Android Studio」を使用した、新しい情報は、
 「ホーム > プログラミング > モデルビューアを作る ( Android + OpenGL ES 1.0/1.1 ) ( Android Studio 2.3.3 版 )」)



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

使用開発環境は、Eclipse 3.7.2 ベースの Pleiades です。

解説

従来、OpenGL では、ピックは、「セレクション」と呼ばれる、セレクションモードと、関連するルーチンを使用して、実現しましたが、OpenGL ES には、「セレクション」はありません。

ピックを実現する方法として、ここでは、バックバッファを利用した方法を採用します。

バックバッファにモデルを描画します。モデルを通常の色で描画するのではなく、それぞれの要素を識別する色で描画します。描画後、ピックしたピクセルの色を読み込み、ピクセルの色からピックした要素を識別します。

実装

プロジェクトを開く

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

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

ピックに関する処理を担うピックOpenGLレンダラクラスを、モデルOpenGLレンダラクラスの派生クラスとして作成します。

パッケージエクスプローラで、作成したプロジェクトの下の「src」の下の作成したパッケージを右クリックし、 右クリックメニューの「新規 > クラス」 を選択します。


名前 にクラス名「OpenGLPickRenderer」、
スーパークラスに、「OpenGLModelRenderer」、
を入力し、「完了」ボタンを押します。

モデル描画関数のオーバーライド

モデルDirect3Dレンダラクラスの描画処理は要素ピックを考慮していません。
ピックDirect3Dレンダラクラスに要素ピックを考慮した描画処理 renderScene関数、renderModel関数 を追加します

モデル描画関数である renderModel関数は、3つのモードを用意します。
描画モードでは通常の色で描画し、要素タイプピック描画モードでは要素タイプ(点、線、面)別の色で描画し、要素番号ピック描画モードでは要素番号別の色で描画するようにします。
描画モードでは、ピック要素に関するハイライト描画も行います。

シーン描画関数である renderScene関数は、描画モードで、モデル描画関数を呼び出します。



・描画のモードに関する 列挙型の定義の追加
・描画要素タイプに関する列挙型の定義の追加

・ピック要素に関する情報を保持する名前列メンバ変数の追加
・ピック要素に関する情報を保持する名前列の大きさ定数の追加

・要素番号別の色で描画するための色バッファーメンバ変数の追加
・要素番号別の色を作成するための、ビットマスク定数の追加
・色バッファーメンバ変数のアクセサの追加
・要素番号を色に変換するメンバ関数の追加

・モデルをセットする関数をオーバーライドし、ピック要素に関する情報を保持する名前列の初期化処理、要素番号別の色で描画するための色バッファーの構築処理を追加

も行います。

要素選択関数の追加

要素選択関数を追加します。

処理の内容としては、以下を実装します。

  1. バックバッファのカラーアタッチメント用に、テクスチャを作成します。
  2. バックバッファーの深度アタッチメント用に、レンダーバッファを作成します。
  3. バックバッファとして、フレームバッファを作成します。
  4. 3. で作成したフレームバッファをバインドします。
  5. フレームバッファのカラーアタッチメントとして、1. で作成したテクスチャを指定します。
  6. フレームバッファの深度アタッチメントとして、2. で作成したレンダーバッファを指定します。
  7. ピック領域分の名前列を作成します。
  8. 要素タイプピック描画モードでモデルを描画し、描画後、ピック領域のピクセルの色を読み取り、要素タイプをピック領域の名前列の2番目にセットします。
  9. 要素番号ピック描画モードでモデルを描画し、描画後、ピック領域のピクセルの色を読み取り、要素番号をピック領域の名前列の3番目にセットします。
  10. 「要素タイプの優先順位は、点、線、面。同じ要素タイプの場合は、ピック領域の中心に近いものが優先」に従い、ピックピクセルを一つに絞ります。
  11. 一つに絞ったピックピクセルの名前列を、メンバ変数の名前列にコピーします。
  12. ウインドウシステムが提供するフレームバッファに差し替えます(ウインドウシステムが提供するフレームバッファをバインドします)。
  13. 1. で作成したテクスチャを削除します。
  14. 2 で作成したレンダーバッファを削除します。
  15. 3 で作成したフレームバッファを削除します。



・ピック領域の上下左右のオフセット量定数の追加
・色を要素番号に変換するメンバ関数の追加
・ピックピクセルを一つに絞る関数の追加

も行います。

モデルビューアビュークラスのレンダラオブジェクトの型の修正

ピックOpenGLレンダラクラスの作成にあわせて、モデルビューアビュークラスを修正します。

・m_rendererメンバ変数を、OpenGLPickRenderer型に変更します。
・m_rendererメンバ変数の生成を、OpenGLPickRendererオブジェクト生成に変更します。

モデルビューアービュークラスに、長押しイベントに関する処理の追加

ModelViewerViewクラスに、ユーザーのピック操作を担う、長押しイベントに関する処理を追加します。

・ModelViewerViewクラスを、GestureDetector.OnGestureListenerインターフェースを実装するクラスに変更(implements節の追加)。
・メンバ変数に、GestureDetectorオブジェクトを追加。
・コンストラクタに、GestureDetectorオブジェクトのインスタンス生成処理の追加
・onTouchEvent関数に、GestureDetectorオブジェクトにイベントオブジェクトを渡す処理を追加。
・GestureDetector.OnGestureListenerインターフェースとして実装しなければならない関数を実装。長押しイベントを担う、onLongPress関数には、ピッキング関数呼び出し処理を追加する。ピッキング関数呼び出しは、UIスレッドからのOpenGL関数呼び出しになるので、イベントキューイングします。

実行

Android Virtual Device にて、動作確認。

※ ターゲット:「Android 4.0.3 - API Level 15」、ハードウェア:「GPU emulation」をyes、として作成したAndroid Virtual Device にて動作確認。

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

ダウンロード

サンプルプロジェクト

関連ページ

前項目:03.モデルOpenGLレンダラクラスを作る

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