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



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

解説

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

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

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

実装

プロジェクトを開く

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

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

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

「Project」ペインの「app > java > ドメイン.modelviewertutorial」を右クリックします。
右クリックメニュー「New > Java Class」を選択します。


Nameに、「OpenGLPickRenderer」、
Superclassに、「com.hiramine.modelviewertutorial.OpenGLModelRenderer」、
を入力し、「OK」ボタンを押します。

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

要素ピックを考慮した描画処理を追加します

・描画のモードに関する 列挙型の定義を追加します。
・描画要素タイプに関する列挙型の定義を追加します。
・ピック要素に関する情報を保持する名前列メンバー変数を追加します。
・ピック要素に関する情報を保持する名前列の大きさ定数を追加します。
・要素番号別の色で描画するための色バッファーメンバー変数を追加します。
・要素番号別の色を作成するための、ビットマスク定数を追加します。
・色バッファーメンバー変数のアクセサを追加します。
・要素番号を色に変換するメンバ関数を追加します。
・モデルをセットする関数をオーバーライドし、ピック要素に関する情報を保持する名前列の初期化処理、要素番号別の色で描画するための色バッファーの構築処理を追加します。



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

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



「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。

要素選択関数の追加

要素選択に必要な処理を追加します。

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



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

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

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



「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。

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

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

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

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

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

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



「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
リビルドし、エラー、警告がないことを確認します。

実行

Android端末にて、動作確認。

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

ダウンロード

サンプルプロジェクト
github.com上のダウンロードページ

関連ページ

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

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