ラベル OpenGL の投稿を表示しています。 すべての投稿を表示
ラベル OpenGL の投稿を表示しています。 すべての投稿を表示

2014年1月4日土曜日

[Android] アナログ時計のアプリをC/C++で改良

Analog clock on OpenGL by Android-NDK
前回の アナログ時計アプリ のOpenGLの部分をC/C++言語で書けるだけ書いてみました。

C/C++を利用した場合、Javaだけで書いたアプリと比べると次のような特徴があります。
・マシン語で動作するコードの比率が増える
・C/C++出使用するオブジェクトはガーベジコレクター(GC)の対象にならない
このおかげでアプリの高速化やバッテリー消費を抑えるなどの効果が期待できます。

今回の開発環境は次の通りです。
・64bit版 Windows8
・32bit版 Eclipse3.7 (Windows XPモードで使用)
・Android-SDK r22.3
・Android-NDK r9

針の画像です。
左から秒針、分針、時針のつもりです。
針の画像それぞれのピクセル数は32×128です。一番右の黒い塗りつぶしの領域は使用しません。

Eclipseのパッケージ・エクスプローラーで、プロジェクトの res フォルダーの下に
drawable-nodpi
というフォルダーを作り針の画像を配置します。

以下ソースです。
※ Android.mk と jni.cpp と glu.h の3つのファイルはEclipseのプロジェクト・エクスプローラーでjniというフォルダーを作ってそこに保存します。

アクティビティ(MainActivity.java)

Android.mk

jni.cpp

glu.h (Android-NDKのsampleの com.example.SanAngeles から抜粋しました)
※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。
SH-03C(実機)、Android-SDK付属のエミュレーター、Blue Stacksで動作することを確認していますが動作保証は出来ません。

エミュレーターのスクリーンショットです。
前回のJavaだけで書いたアプリと同じように動作するように作ったので見た目の変化はありません。
1秒に1回しか画面が変化しないので、ログまでチェックしないとGCが減ったかどうかは分かりにくいですね。

関連ブログ
[Android] アナログ時計のアプリを作ってみました
[Android] ストップウォッチアプリの表示をC言語でスムーズに改造する
[Android] ストップウォッチアプリを作ってみました
[Android] 方位センサーを使ってコンパスアプリを作る
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Windows8][Android] Can't bind to local 8600 for debugger
[Android] 端末の傾きに立方体を連動させる
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] Android-NDKでテクスチャを表示するには
[Android] OpenGLで頂点の多いポリゴンを扱うには

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

2013年12月28日土曜日

[Android] アナログ時計のアプリを作ってみました

Analog clock on OpenGL
先日、時計が壊れてしまいました。デジタル時計は身近なところにありますが、アナログ時計は意外と少ないのでアプリを作ってみました。
画像の回転して表示する処理が必要なのでOpenGLを利用します。

今回の開発環境は次の通りです。
・64bit版 Windows8
・32bit版 Eclipse3.7 (Windows XPモードで使用)
・Android-SDK r22.3

針の画像です。
左から秒針、分針、時針のつもりです。
針の画像それぞれのピクセル数は32×128です。OpenGLで扱う画像なので128×128ピクセルにしたかったので一番右の黒い塗りつぶしの領域は使用しません。

Eclipseのパッケージ・エクスプローラーで、プロジェクトの res フォルダーの下に
drawable-nodpi
というフォルダーを作り針の画像を配置します。

以下ソースです。

アクティビティ(MainActivity.java)

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。
SH-03C(実機)、Android-SDK付属のエミュレーター、Blue Stacksで動作することを確認しています。

動作保証はできませんがとりあえず動作するようです。
SH-03Cで実行してみた画像です。
針の角度は1秒ごとに変化するようにしました。

これだけだと現在時刻が分かりにくいですね。
針の画像をかっこよくしたり文字盤の画像を追加すると実用性が上がるかもしれません。

関連ブログ
[Android] ストップウォッチアプリの表示をC言語でスムーズに改造する
[Android] ストップウォッチアプリを作ってみました
[Android] 方位センサーを使ってコンパスアプリを作る
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Windows8][Android] Can't bind to local 8600 for debugger
[Android] 端末の傾きに立方体を連動させる
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] Android-NDKでテクスチャを表示するには
[Android] OpenGLで頂点の多いポリゴンを扱うには

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

2013年8月24日土曜日

[Android] 端末の傾きに立方体を連動させる

How to detecot the tilt
端末の傾き具合を検知するアプリを作りました。

傾きを検知するに当たりTechBooster様のコンテンツを参考にしました。
http://techbooster.jpn.org/andriod/ui/443/

傾き具合を数字で表示しても分かりにくいので立方体(キューブ)で表示します。
立方体の表示はAndroid SDK付属のOpen GLのサンプルを流用します。
端末の傾き取得のため磁界センサーと加速度センサーの両方を使います
両方のセンサーをもつ端末が必要です。中華PadのONDA Vi30は必要なセンサーがありませんでした。
センサーから得られる値がラジアンなので角度に変換するなど 前回の方位磁石アプリ
に比べるとソースがどちょっと複雑です。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit)(XP互換モードで起動)
・Android SDK r22.0.1

以下ソースです。

MainActivity.java (Activity)

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。

実行する端末を動かすたびに立方体が回転します。
SH-03Cで動作させるとセンサーのノイズが多いのか、端末が静止していても立方体がプルプル動きます。
方位センサーほどの精度は期待できないようです。

関連ブログ
[Android] 方位センサーを使ってコンパスアプリを作る
[Android] Javaのstaticクラスから非sataticメソッドを呼び出すには
[Android] OpenGLの簡易画像ビュアーにSDカード内の画像を表示する
[Windows8][Android] Can't bind to local 8600 for debugger
[Android] Android-SDKでやってはいけないこと
[Android] Toastに画像やボタンを表示するには
[Android] ライブ壁紙の作り方
[Android] Activityに時計を表示する(Activityの非同期更新)
[Android] Webコンテンツを強制的に表示するには
[Android] Toastをcancelするには

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

2013年6月29日土曜日

[Android] OpenGLの簡易画像ビュアーをAndroid-NDKでビルドする (失敗談)

OpenGL and JNI
AndroidアプリをAndroid-NDKで開発するとネイティブコード(Javaインタープリターを通らないマシン語)で書かれたJNI(Java Native Interface)の動作比率を増やすことができ、Javaだけで開発したアプリに比べて高速な動作やバッテリーの長持ちが期待できます。
Android-NDKで開発するデメリットとして「マルチプラットフォーム(CPUが異なる端末)で動作しなくなる」という点があげられます。
Android-NDK-r8d では
・armeabi
・armeabi-v7a
・MIPS
・x86
の4種類のCPUがサポートされています。
PowerPC系のAndroid端末が普及しない限りマルチプラットフォームの心配はないようです。
そこで、 前回 公開したOpenGLによる簡易画像ビュアーをAndroid-NDKに移植してみました。

Android-NDKの弱点
アプリケーションのresフォルダーに保存された画像や音声ファイルを直接読み込む方法がありません。
SDカードに保存された画像ファイルなら読み込むことはできますが、画像をテクスチャに表示するためには画像ファイルをBitmap(1次元配列)にデコードする必要があります。
ところがAndroid-NDKには画像ファイルをデコードするライブラリーが見当たりません。
Android-NDKで画像を扱うには次の選択肢があります。

1. AndroidのJavaのAPIで画像ファイルをデコードしたint配列をJNIに渡す。
2. 画像ファイルをデコードする処理をC/C++で自作する。
3. C言語で書かれたオープンソースの画像ローダーを利用する。

デバッグのしやすさから1番目の方法で画像ファイルをNDKで扱うことにします。

留意点
Android端末の機種によりますが、ビットマップ画像の扱い中にOutOfMemoryErrorが起きやすいです。
SH-03C(Android2.2)は 1440x1440ピクセルの画像を int配列(約8MB)にバッファーしようとすると必ず次のエラーが発生します。
Out of memory on a 8294416-byte allocation.
試行錯誤した結果、今回は次のような仕様にしました。

1. Javaで画像ファイルを読み込み、512×512に伸縮する。
2. 伸縮した画像をint配列に変換しJNIに渡す。
3. JNIのOpenGL APIで画像をテクスチャとして表示する。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit) (XP互換モードで起動)
・Android SDK r21.0.1
・Cygwin
・Android-NDK-r8d
※Android-NDKのビルド方法は環境に強く依存するため省略します。

2点以上のタッチ操作が必要なので、Android2.2以降でマルチタッチ対応の端末が必要です
新品で発売されているAndroid端末なら、中華Padも含めてほぼど対応していると思います。

以下ソースです。

MainActivity.java
jni.cpp
glu.h (Android-NDKのsampleの com.example.SanAngeles から抜粋しました)
Android.mk
jni.cpp、glu.h、Android.mk はプロジェクトにjniというフォルダーを追加して、そこにコピーします。
※特別な権限(Permission)は不要なのでマニフェストは省略します。
Android2.2以降で動作します。
Target SDK Version が8以上の設定でビルドできます。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。

留意点でも書きましたが、古いスマートフォン(Android2.2以前)で実際に使ってみると 前回のJavaだけで作ったアプリに比べて
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
が起きやすいです。
画像をint配列に変換するためのメモリーを確保したり、その逆の変換をするためのメモリーを確保したりするためメモリーの空き領域が不足がちになるようです。
さらにJavaだけで書いたアプリと体感速度を比べるても差がありませんでした。
当初の予想とは裏腹にデメリットの方が多かったのでタイトルに「失敗談」と付けました。

Android4.0なら安定して動作しますが体感速度は変わりません。

関連ブログ
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ #2
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] OpenGLで簡易画像ビュアーを作る
[Android] ジェスチャーでOpenGL簡易画像ビュアーに拡大縮小機能を追加する
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Android] OpenGL ESで文字を表示する
[Android] OpenGLで頂点の多いポリゴンを扱うには
[Android] OpenGLでシャープ製端末用3D(立体視)アプリケーションを作る
[Blender] obj2opengl.plをJava用に改造する
[Windows8][Android] Can't bind to local 8600 for debugger


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

2013年6月22日土曜日

[Android] OpenGLの簡易画像ビュアーにSDカード内の画像を表示する

How to load the image files in a SD card

前回 はフリーサイズの画像を伸縮してOpenGL APIで表示するアプリを作りました。
このアプリはプロジェクトのリソースとして組み込んだ画像しか表示することができません。
今回はSDカードに保存されている画像をOpenGL APIで表示するアプリを作ります。
既に次の様な操作方法が実装済みです。
・スクロールで移動
・ピンチアウトで拡大
・ピンチインで縮小

SDカードには複数の画像ファイルが保存されているとし、一枚ずつ表示する画像を差し替えていきます。
画像を差し替える操作方法
・画面の左から右へ大きくスワイプしたら次の画像を表示
・画面の右から左へ大きくスワイプしたら前の画像を表示
とします。
画面の横幅の半分以上の距離をスワイプしたら画像を差し替える様にします。

画像の表示順は画像ファイル検索時に見つけた順です。
表示する画像の種類は拡張子が「.png」「.jpg」「.jpeg」「.gif」のファイルとします。拡張子の大文字小文字は区別しません。
隠しファイルに設定されている画像ファイルや隠しフォルダーに保存されている画像ファイルは表示しないことにします。

ところでAndroid端末のSDカードのパスは機種ごとに異なります
実際に手持ちの機種で調べたところメーカーごとに違うことを確認しています。
SDカードのパスを取得するに当たり
とむ・やむくんさんの 戌印-INUJIRUSHI- (Androidあれこれ)
http://inujirushi123.blog.fc2.com/blog-entry-30.html
を参考にさせて頂きました。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit) (XP互換モードで起動)
・Android SDK r21.0.1

SDカード内の画像ファイルの検索は時間がかかるので AsyncTask を使います。
検索が完了したら最初に見つけた画像を表示します。

以下ソースです。

Activity(MainActivity.java)

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Android2.2以降で動作します。
Target SDK Version が8以上の設定でビルドできます。

実行すると下の様になります。
本のページをめくるようにフリックするとスマートフォンのカメラ機能で撮影した画像や保存したスクリーンショットが次々と表示されます。

関連ブログ
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] OpenGLで簡易画像ビュアーを作る
[Android] ジェスチャーでOpenGL簡易画像ビュアーに拡大縮小機能を追加する
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Android] OpenGL ESで文字を表示する
[Android] OpenGLで頂点の多いポリゴンを扱うには
[Android] OpenGLでシャープ製端末用3D(立体視)アプリケーションを作る
[Blender] obj2opengl.plをJava用に改造する
[Windows8][Android] Can't bind to local 8600 for debugger

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

2013年6月15日土曜日

[Android] フリーサイズの画像をOpenGLのテクスチャに表示する

How to stretch and reduce images.
前回までに作ったOpenGLで簡易画像ビュアーの機能を強化します。
ピンチイン・ピンチアウトの認識とOpenGL ES 2.0 のAPIを利用するので、Android2.2以降でマルチタッチ対応の端末が必要です。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit) (XP互換モードで起動)
・Android SDK r21.0.1

OpenGLで画像をテクスチャとして表示するためには、辺の長さが2の累乗(べき乗)の正方形である必要があります。
256×256ピクセル、512×512ピクセルなど。
このルールを守らないと端末によってはテクスチャが表示されないことがあります。

OpenGLの仕様とは言え、表示したい画像が全て正方形とは限りません。
今回は、縦と横のサイズが異なる画像を伸縮し、OpenGLで表示できる様にします。
そして1画面に2枚の画像を表示します。

300×200ピクセルの orientation.png


200×300ピクセルの portrait.png

二つの画像ファイルをプロジェクトの
res - drawable-mdpi
にコピーします。
resフォルダーの下に drawable-nodpi というフォルダーを作ってそこに画像ファイルをコピーしてさい
drawable-nodpi 以外のフォルダーに保存した画像は端末の解像度に応じて自動でスケーリングされるようです。(2014年5月31日訂正)
※ ic_launcher.png はAndroid-SDKのデフォルトでインストールされるアイコン画像です。

フリーサイズの画像をテクスチャに表示するため伸縮させ正方形に納めます。余白は透明のピクセルで埋めます。

伸縮させた画像がギザギザにならないようにMatrixを使ってアンチエイリアス処理をします

Activity(MainActivity.java)

2013年6月8日土曜日

[Android] ジェスチャーでOpenGL簡易画像ビュアーに拡大縮小機能を追加する

How to enlarge and reduce images on gestures
前回前々回はOpenGL APIを使って画像を表示するアプリを作りました。
今回はジェスチャーのピンチイン・ピンチアウトの操作で画像を拡大縮小する機能を追加します。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit) (XP互換モードで起動)
・Android SDK r21.0.1

2点以上のタッチ操作が必要なので、Android2.2以降でマルチタッチ対応の端末が必要です
新品で発売されているAndroid端末なら中華Padも含めてほぼ対応していると思います。
Android2.2以降を対象にするため、OpenGL ES 2.0 のAPIも利用します。

画像は前々回と同じ256×256ピクセルのものを使います。


画像ファイル(image256x256.png)はプロジェクトの
res - drawable-mdpi
にコピーします。
resフォルダーの下に drawable-nodpi というフォルダーを作ってそこに画像ファイルをコピーしてさい
drawable-nodpi 以外のフォルダーに保存した画像は端末の解像度に応じて自動でスケーリングされるようです。(2014年5月31日訂正)

※ ic_launcher.png はAndroid-SDKにデフォルトでインストールされるアイコン画像です。

ピンチイン・ピンチアウトの操作に対応させるため OnScaleGestureListener インターフェイスを継承します。
※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が8以上の設定でビルドできます。

Activityクラス (MainActivity.java)

画像を拡大縮小するに当たり GLU.gluPerspective の視野角を変化させます。

なぜ拡大縮小に視野角を利用したか
将来、複数の画像を表示させたいと思ってます。
複数の画像を並べて表示し拡大縮小した場合、それぞれの画像の位置関係を保ったまま画像を拡大縮小したように見せるためです。
拡大縮小の処理をそれぞれの画像のサイズを変える方法では、拡大した複数の画像が重ならない様に位置を調整する必要があり処理が複雑になってしまいます。
描く画像の位置関係を保ったまま拡大縮小した様に見せるため、視野角を変化させる方法を採用しました。
ただし視野角を変化させると立体的な見え方が不自然になることがあります。
このアプリは平面を表示するだけなので視野角を変化させても弊害はありません。
視野角を変化させるほか、カメラの位置を近づけたり遠ざけたりする方法もいいと思います。

OpenGL ES 2.0 のAPIである GLES20.glTexParameteri を使ってテクスチャーの表示方法をClipに指定します。

Android2.2にバージョンアップしたdocomoのSH-03C(シャープ)で動作確認しました。
フリックで移動、ピンチアウトで拡大、ピンチインで縮小です。

これでOpenGLで作ったメリットが発揮されました。

関連ブログ
[Android] OpenGLで簡易画像ビュアーを作る
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Android] OpenGL ESで文字を表示する
[Android] OpenGLで頂点の多いポリゴンを扱うには
[Android] OpenGLでシャープ製端末用3D(立体視)アプリケーションを作る
[Blender] obj2opengl.plをJava用に改造する
[Windows8][Android] Can't bind to local 8600 for debugger

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

2013年5月25日土曜日

[Android] OpenGLでプロ生ちゃんをアニメーションさせる

How to make PRONAMA-CHAN run
前回はOpenGL APIを使って画像を表示アプリを作りました
今回はOpenGLで画像をパラパラマンガのようにアニメーションさせます。

アニメーションを表示させるに当たり、プログラミング生放送で公開されている「プロ生ちゃん(暮井 慧)」のドット絵画像を使います。
「プロ生ちゃん」の利用ガイドラインはこちら

512×512ピクセルの画像にプロ生ちゃんのドット絵パターンを並べてみました。
一つのパターンは64×64ピクセルです。

※以下、「パターン」という言葉をプロ生ちゃん一人分の画像という意味で使用します。

全部で16パターンありますが今回は上の段の6パターンを使ってプロ生ちゃんが走っているように見えるアプリを作ります。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit) (XP互換モードで起動)
・Android SDK r21.0.1

画像ファイルは kurei_kei.png というファイ名で保存しプロジェクトの
res - drawable-mdpi
にコピーします。
resフォルダーの下に drawable-nodpi というフォルダーを作ってそこに画像ファイルをコピーしてさい
drawable-nodpi 以外のフォルダーに保存した画像は端末の解像度に応じて自動でスケーリングされるようです。(2014年5月31日訂正)

※ ic_launcher.png はAndroid-SDKにデフォルトでインストールされるアイコン画像です。

gl.glTexCoordPointer でテクスチャの表示範囲(マッピング)を指定しします。
1つのパターンは画像8分の1のサイズなので幅と高さはそれぞれ 0.125 です。
マッピングは横方向は左から右に向かって、縦方向は上から下に向かってプラスになるので、左上のパターンを例にとると座標は下の様になります。

マッピング座標をハードコーディングしてもいいのですが、将来パターンが増えた場合に備えて計算で求めることにしました。
今回のソースでは、パターンごとのマッピング座標は配列の keiCoordsBuffs[] にバッファします。順番は次の通りです。

1から6までのパターンを0.1秒ごとに差し替えてアニメーションさせます。

アクティビティ(MainActivity.java)

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。

実際に走っている姿は躍動感があります。
前回のソースを元にしているのでフリックで画像を移動できます。

ドットバイドット表示するために gl.glTexParameterf のパラメーターを指定しているのですが機種によって対応が異なるようです。


関連ブログ
[Android] OpenGLで簡易画像ビュアーを作る
[Android] OpenGL ESで文字を表示する
[Android] OpenGLで頂点の多いポリゴンを扱うには
[Android] OpenGLでシャープ製端末用3D(立体視)アプリケーションを作る
[Blender] obj2opengl.plをJava用に改造する
[Windows8][Android] Can't bind to local 8600 for debugger


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