01.ベースOpenGLレンダラクラスを作る
プロジェクトの作成を行います。
OpenGLの初期化処理と終了処理を行い、OpenGLを用いた描画処理の骨格を担う、ベースOpenGLレンダラクラスを作成します。
解説
Androidで、OpenGLを使用して描画をするためにすべきことは、以下です。
- GLSurfaceView.Rendererインターフェースを実装したクラスのオブジェクトを生成する。
- GLSurfaceViewクラス(もしくは、その派生クラス)のオブジェクトを生成する。
- 1.で作成したGLSurfaceView.Rendererオブジェクトを、2.で作成したGLSurfaceViewオブジェクトに、setRenderer関数でセットする。
- 2.で作成したGLSurfaceViewオブジェクトを、メインアクティビティの、onCreate関数内で、setContentView関数でセットする。
- GLSurfaceView.Rendererインターフェースを実装したクラスの、サーフェースが作成された時およびサーフェースが再作成された時に呼び出される onSurfaceCreated関数で、クリアカラーの設定や、クリア深度設定、およびOpenGLの有効、無効の設定をする。
- GLSurfaceView.Rendererインターフェースを実装したクラスの、サーフェースが変更された時に呼び出される onSurfaceChanged関数で、ビューポートの設定、視野角錐台の設定、視点座標変換の設定をする。
- GLSurfaceView.Rendererインターフェースを実装したクラスの、フレームを描画する時に呼び出されるonDrawFrame関数で、モデル描画の処理をする。
Androidで、OpenGLを使用して描画をするときに、した方がよいことは、以下です。
- メインアクティビティクラスの、他のアクティビティが起動したことでバックグラウンドに追いやられた時に呼び出される onPause関数で、GLSurfaceViewオブジェクトのonPause関数呼び出しを行う。
- メインアクティビティクラスの、ポーズから復帰する時に呼び出される onResume関数で、GLSurfaceViewオブジェクトのonResume関数呼び出しを行う。
Androidで、OpenGLを使用して描画をするときに、しなくても良いが、今回やっていることは、以下です。
- GLSurfaceViewの描画モードは、既定では、RENDERMODE_CONTINUOUSLYという、絶え間なく描画するというモードになっていますが、RENDERMODE_WHEN_DIRTYという、描画要求があったときだけ描画するというモードに変更しています。描画要求は、requestRenderという関数で行います。
実装
プロジェクトの作成
プロジェックとを作成します。
「Welcome」画面の「Start a new Android Studio project」をクリックします。
Application name、に「ModelViewerTutorial」と入力します。
Company domain、に会社のドメイン名を指定します。
Project location、にプロジェクトを保存するフォルダパスを指定します。
「Next」ボタンを押します。
Minimum SDKを選択します。今回は、「API19: Android 4.4 (KitKat)」にしました。
「Next」ボタンを押します。
「Empty Activity」を選択し、「Next」ボタンを押します。
(変更なし)
「Finish」を押します。
Target SDKのバージョンの変更
Androidのバージョンの違いによる振る舞いの違いを抑制したいので、Targe SDKのバージョンを、Minimum SDKで指定したバージョンに揃えます。
「Project」ペインの「Gradle Scripts > build.gradle (Module.app)」を開きます。
「targetSdkVersion」行を探し、
「targetSdkVersion 19」に変更します。
ファイルを上書き保存します。
メニュー「Build > Rebuild Project」で、リビルドし、エラー、警告がないことを確認します。
ベースOpenGLレンダラクラスの作成
OpenGLを用いた描画処理の骨格を担う、ベースOpenGLレンダラクラスを作成します。
GLSurfaceView.Rendererインターフェースを実装したクラスとして作成します。
「Project」ペインの「app > java > ドメイン.modelviewertutorial」を右クリックします。
右クリックメニュー「New > Java Class」を選択します。
Nameに、「OpenGLBaseRenderer」、
Interfaceに、「android.opengl.GLSurfaceView.Renderer」、
を入力し、「OK」ボタンを押します。
サーフェースが作成された時、再作成された時の処理の実装
GLSurfaceView.Rendererインターフェースを実装したクラスの、サーフェースが作成された時およびサーフェースが再作成された時に呼び出される
onSurfaceCreated関数に、OpenGLオブジェクトに関するメンバー変数への設定、クリア処理の設定、クリア処理の設定、ポリゴン処理の設定、ライティング処理の設定、ブレンド処理の設定を追加します。
OpenGLオブジェクトに関するメンバー変数およびアクセサを追加します。
「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
サーフェースが変更された時の処理の実装
GLSurfaceView.Rendererインターフェースを実装したクラスの、サーフェースが変更された時に呼び出される onSurfaceChanged関数に、サーフェースのサイズに関するメンバー変数への設定、ビューポートの設定、視野角錐台の無効化、視点座標変換の無効化、の処理を追加します。
サーフェースのサイズに関するメンバー変数およびアクセサ関数、ビューポート設定関数を追加します。
視野角錐台設定、視点座標変換設定は、OpenGLの変換行列を変更するとき以外は設定する必要はありません。必要なときのみ設定することで、描画処理の負担を軽減するようにします。設定を実施する必要があるかを判断するための設定の有効性メンバー変数、アクセサを追加します。
「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
フレーム描画処理の実装
GLSurfaceView.Rendererインターフェースを実装したクラスの、フレームを描画する時に呼び出されるonDrawFrame関数に、モデル描画の処理を追加します。
視野角錐台設定、視点座標変換は、設定の有効性メンバー変数に応じて実施するようにします。
視野角錐台設定、視点座標変換設定、シーン描画前の処理、シーン描画後の処理、ストックシーンの描画、シーン描画、軸の描画、byteバッファーの作成、shortバッファーの作成、floatバッファーの作成の関数を追加します。
また、byte型のバイト数、short型のバイト数、float型のバイト数の定数変数を追加します。
また、軸描画用の頂点バッファーメンバー変数、色バッファーメンバー変数を追加します。
また、コンストラクタを追加し、コンストラクタに、軸描画用の頂点バッファーメンバー変数、色バッファーメンバー変数の構築処理を追加します。
「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
レイアウトの変更
メインアクティビティのレイアウトを変更します。
「Project」ペインの「app > res > layout > activity_main.xml」を開きます。
ルートレイアウトを「LinearLayout」に変更します。
OpenGL用のViewとして、GLSurfaceViewを設置します。
activity_main.xmlの内容を以下のようにします。
メインアクティビティクラスの実装
メインアクティビティの、onCreate関数内で、以下を行います。
- ビューからGLSurfaceVeiwオブジェクトを取得します。
- GLSurfaceView.Rendererインターフェースを実装した「OpenGLBaseRenderer」クラスのオブジェクトを生成します。
- 2.で生成した「OpenGLBaseRenderer」オブジェクトを、1.で取得したGLSurfaceViewオブジェクトに、setRenderer関数でセットします。
また、GLSurfaceViewクラスのオブジェクトメンバー変数を追加します。
また、GLSurfaceViewの描画モードは、既定では、RENDERMODE_CONTINUOUSLYという、絶え間なく描画するというモードになっていますが、RENDERMODE_WHEN_DIRTYという、描画要求があったときだけ描画するというモードに変更します。(描画要求は、requestRenderという関数で行います。)
他のアクティビティが起動した場合等には、OpenGLの処理を一時中断するようにします。
メインアクティビティに、「初回表示時、および、ポーズからの復帰時」に呼ばれる関数である onResume関数と、「別のアクティビティ(か別のアプリ)に移行したことで、バックグラウンドに追いやられた時」に呼ばれる関数である
onPause関数を追加します。
「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
リビルドし、エラー、警告がないことを確認します。
実行
Android端末にて、動作確認。
軸が表示されます。
ダウンロード
サンプルプロジェクト
(github.com上のダウンロードページ)