2011年7月16日土曜日

[Android] OpenGLで頂点の多いポリゴンを扱うには

How to draw many vertrics on GLSurfaceView

前回のブログobj2opengl.plをJava用に改造する では
obj2opengl: convert obj 3D models to arrays compatible with iPhone OpenGL ES « Heiko Behrens (Blog):
http://heikobehrens.net/2009/08/27/obj2opengl/
で公開されているバナナのオブジェクトは頂点が多くてJavaでは扱えないことがわかりました。

原因は
定数プールは65536エントリー以内
コンストラクターやメソッドのソースは65536バイト以内
というJavaの仕様によるものでした。

Javaは大きいソースをビルドできないので、外部ファイルに持たせる方法をいくつか試してみましたがどれも無理でした。

1.assetsフォルダーに頂点データをテキストファイルに保存する
→AssetManagerは256行以上のテキストファイルを読み込めない(IOException例外が発生)

2.頂点データをvalues/strings.xmlに保存する
→strings.xmlは65536行以上のデータを扱えない

試行錯誤の結果、obj2opengl.plが出力したbanana.hをAndroid-NDKで使うことでバナナを表示できました
HBehrens-obj2opengl-a0f123e.zipに含まれるbanana.jpgとbanana.hをAndroidプロジェクトに取り込みます。
jniフォルダーを作ってbanana.hを保存します。
drawableフォルダーを作ってbanana.jpgを保存します。
jniフォルダーにはさらにAndroid.mkとbanan.cppを保存します。

Android.mk
banana.cpp
Activityのソースです。
Main.java(Activity) これでカレントフォルダーをプロジェクトのjniフォルダーに移動し、ndk-buildを実行します。

起動するとこうなります。
画面をドラッグすると視点が動くようにしました。
バナナとバナナの中心点がかなり離れてるようで(気のせいでした)、大きく動かすと画面から消えてしまいます。

今回は頂点の配列をAndroid-NDK、それ以外をJavaで書いたのでエミュレーターで実行するとすごく遅いです
FloatBufferの作成にすごく時間がかかります。バナナが表示されるまで2分くらいかかりました。
FloatBufferをシリアライズできればもっとスマートになるんですが。

Blenderモンキーの頂点+法線ベクトルの組み合わせもソースが大きくてJavaではビルドできませんでした。objファイルをobj2opengl.plでhファイルに変換し、バナナと同じようにAndroid-NDKでビルドしました。光源で照らしてます。こちらはテクスチャがないのでエミュレーターに表示されるまで30秒くらいでした。

Android-NDKを使うデメリットはARMプラットフォームの端末しかサポートきなくなることです。x86版Android端末にはインストールすらできなくなります。
ただし、今のところ国内のAndroid端末はほとんどがARMベース(Qualcomm、Tegraなど)なので大きなデメリットではないと思います。

以上、参考になれば幸いです。

4 件のコメント:

  1. こんにちは。
    私もiPhoneで【obj2opengl.pl】を使っているのですが、
    表示されるものと表示されないものがあります。
    バナナが表示できなく、私も中心点を疑っていますが、
    原因を特定できていません。

    私の場合、エミュレータのほうが実行速度が速く、確認を2分以上待って行っていますが、表示されません。
    原因をご存知でしたらお教えいただけませんでしょうか?

    返信削除
    返信
    1. コメントありがとうございます。
      大変お困りかと思いますが、iPhoneやXcodeでの検証はしていないので残念ながらお答えできる情報がありません。
      テクスチャ無しの平面や立方体など複数の簡単なモデルデータが背景と異なる色で表示できるか試してみてはどうでしょうか?

      削除
    2. ご回答ありがとうございます。
      色々と試してみたいと思います。

      削除
    3. 返信ありがとうございます。

      削除