AndroidでOpenGLしてみた

GW直前に運良くAndroid端末を借りることができたので、このGWは以前作ったOpenGLのテストアプリをAndroidに移植するのに費やした。

・実行画面(シミュレーター)

ドラッグして離すと、反対方向に回る。

・Android用実行ファイル
AndroidPolygonSphereTest.apk

・ソースコード
AndroidPolygonSphereTest.tgz
Android SDKの"ApiDemos"(Eclipseで"Android Sample Project"を作成すると選択できる)の中のGLSurfaceViewを使用したサンプルコードに毛を生やした程度のもの。
Activityがどういう状態になったらどうすべきか等のAndroid特有の制御は全く理解していない。
見よう見まねで書いてみたら動いた、というだけのものである。

・コンパイル方法
Eclipse+Android SDKで"Android Application Project"を"Blank activity"付きで作成して*.javaを上書きして"Run As"->"Android Application"でbin/に.apkファイルができる。


感想として、AndroidのGLSurfaceViewはGLUTとは勝手が違うのは当然だが、OpenGLの動作も何か癖があるような気がする。1つ嵌まったのは、glMaterialfv()で光源に対する材質の設定をする時に、第2引数に GL_FRONT_AND_BACKを指定すると意図通りに動くのに、GL_FRONTやGL_BACKを指定すると何も起こらなかったことである。ApiDemosのサンプルコードと異なる部分をつぶさに調べてやっと、GL_FRONT_AND_BACKにすると直ることがわかったが、GL_FRONTではいけない理由は結局分からなかった。カリングのせいだろうと思って、glEnable(GL_CULL_FACE)したりglDisable(GL_CULL_FACE)したり、ポリゴンの頂点の順序を逆にして表裏を切り替えたりしてみたが、結果は変わらなかった。

基本的なことでは、GLSurfaceViewをデフォルト状態で使うと、何のイベントも変化も無くてもonDrawFrame()が間髪入れずに呼ばれ続ける(初期設定がRENDERMODE_CONTINUOUSLYになっている)ことに、しばらく気付かなかった。アニメーションのあるサンプルコードがタイマー駆動しなくてもアニメーションしているのを見て、やっと気付いた。それからも、この挙動はsetRenderMode(RENDERMODE_WHEN_DIRTY)で止めて、再描画はrequestRender()で行うのが妥当だということに行き着くのにも手間取った。

それから、Android APIにandroid.opengl.GLES10, javax.microedition.khronos.opengles.GL10という2つのクラスがあるが、Android Developersのサイトには前者の方がパフォーマンスが良いようなことが書かれているが、詳しく調べるのが面倒くさそうなので、最初に見たApiDemosのサンプルコードで使われていた後者のGL10を最後まで使い続けた。