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

2011/11/18

コマンドラインでANE

随分と久しぶりの更新になってしまいました。タイの洪水の影響とかいろいろあって本業の方が忙しく、まとまった時間を取ることが出来なかったのでした。ようやく落ち着いたので、いろいろ気になってたことをまたぼちぼち試して行きたいと思います。

さて、今回はANEことAIR Native Extensionを取り上げたいと思います。と言っても既に世の中には沢山の事例が出てますので、何を今更という感じでしょうか?

ただ、世の中にあるほとんどのサンプルがFlash Builder4.5.1を持っていることを前提にしてますよね?いやいや、ちょっと待て、俺は持ってねーぞ、という方も中には居らっしゃることでしょう。

そこで、Flex SDKとAIR3.0 SDKとAndroid SDK(Eclipse)でAIR for Android向けにANEを使ったアプリをコマンドラインでビルドする方法を今回は解説します。

その前にANEって何?って人はAKABANAのAIR 3 Native Extension Seriesをひと通り事前に読んで内容を理解しておいてください。

今回は、ExtensionContextやAIR for Androidを拡張するJavaクラスの書き方等は特に解説しません。あくまでも、それのビルド方法にフォーカスして説明します。

ってことで、具体的なビルドの手順は以下のような感じで進めて行きます。

  • ExtensionContextのビルド
  • JARファイルの作成
  • ANEファイルの作成
  • AIRアプリのビルド
  • Android apkファイルの作成

0. AneLab-HelloWorldの入手
説明を進めるのに、題材としてane-labにあるhelloworldを使いたいと思いますので、入手してください。
$ svn checkout http://ane-lab.googlecode.com/svn/trunk/mobile/android/java/helloworld helloworld
以降、コードをcheckoutしたフォルダーを[HELLOWORLD_HOME]と記載します。

1. ExtensionContextのビルド
ExtensionContextというのは、AIRからネイティブライブラリーの中にある関数を呼び出すためのクラスですね。こいつはcompcを使ってSWCにします。ソースは、[HELLOWORLD_HOME]/AneLab-HelloWord-ane/src以下にあります。
$ cd [HELLOWORLD_HOME]/AneLab-HelloWord-ane
$ compc -source-path ./src -include-classes com.example.ane.android.helloworld.HelloWorldExtension -external-library-path [AIR3SDK_HOME]/frameworks/libs/air/airglobal.swc -output ./bin/AneLab-HelloWorld-ane.swc

2. JARファイルの作成
AIR for Androidを拡張するJavaクラスをJARファイルにまとめます。ここだけはコマンドラインでやるのでは無くて、Eclipseの機能を使います。

プロジェクトファイルは[HELLOWORLD_HOME]AneLab-HelloWorld-Java以下にあるので、これをEclipseに既存のプロジェクトとして取り込んでください。

JARファイル化はとても簡単で、まずJARファイルにするプロジェクトを選択したら、コンテクストメニューからExport...を選択します。


すると表示されるダイアログでJAVAフォルダ内のJAR fileを選択し、Next>ボタンを選択して次に進みます。


そしたら、書き出し先を選択(ここでは、[HELLOWORLD_HOME]/AneLab-HelloWorld-ane/platform/android)して、Finishボタンを選択して終了です。


3. ANEファイルの作成
ここまで進んだら、いよいよaneファイルの作成と進みますが、その前に、先程作ったSWCファイルをunzipしたら得られるlibrary.swfを[HELLOWORLD_HOME]/AneLab-HelloWorld-ane/platform/androidに置いておきます。
$ cd [HELLOWORLD_HOME]/AneLab-HelloWorld-ane/bin
$ unzip AneLab-HelloWorld-ane.swc
$ mv library.swc ../platform/android
そしたら、AIR 3 SDKのadtコマンドを使ってANEファイルにパッケージします。
$ cd [HELLOWORLD_HOME]/AneLab-HelloWorld-ane
$ adt -package -storetype pkcs12 -keystore test.p12 -target ane AneLab-HelloWorld-ane.ane extension.xml -swc ./bin/AneLab-HelloWorld-ane.swc -platform Android-ARM -C ./platform/android .
今回のサンプルで使用する認証ファイル(test.p12)に設定されているパスワードに関しては、[HELLOWORLD_HOME]/AneLab-HelloWorld-ane/readme.txtの中身をご参照ください。

4. AIRアプリのビルド
AIRアプリのビルドは通常通りamxmlcコマンドを使えば良いのですが、通常と違うのは外部ライブラリーとして、先程作成したANEファイルを指定することです。AIRアプリは[HELLOWORLD_HOME]/AneLab-HelloWorld-app以下にありますが、コンパイル前に先程作成したaneファイルをlibsフォルダーにコピーしておきます。
$ cd [HELLOWORLD_HOME]/AneLab-HelloWorld-app
$ cp ../AneLab-HelloWorld-ane/AneLab-HelloWorld-ane.ane ./libs
$ cd src
$ amxmlc +configname=airmobile -compiler.external-library-path+=../libs/AneLab-HelloWorld-ane.ane AneLabHelloWorld.mxml
+configname=airmobileを指定するのを結構忘れがちなので、ご注意ください。

5. Android apkファイルの作成
ここまで来れば、最後にadtコマンドを使ってAndroidのapkファイルにパッケージするだけです。事前に作成したアプリのSWFファイルとAIRのアプリケーション記述ファイル(AneLabHelloWorld-app.xml)を[HELLOWORLD_HOME]AneLab-HelloWorld-appにコピーして置きます。

また、コマンドラインでコンパイルする関係上、AneLabHelloWorld-app.xmlの49行目の<content>タグにアプリのswfファイルを指定しておかないとエラーになりますので、編集しておいてください。
$ cd [HELLOWORLD_HOME]/AneLab-HelloWorld-app
$ cp src/AneLabHelloWorld-app.xml src/AneLabHelloWorld.swf .
$ adt -package -target apk -storetype pkcs12 -keystore test.p12 AneLabHelloWorld.apk AneLabHelloWorld-app.xml AneLabHelloWorld.swf -extdir ./libs
普段と違うのは、-extdirにaneファイルを置いてあるフォルダーを指定するくらいですね。

これで無事にapkファイルが作成されたと思いますので、インストールしてちゃんと外部拡張が機能するか確かめてみてください。

■あとがき
今回は既存のファイルを使ったので特にトラブル無く進んだと思いますが、自分で新規に作成する場合は、AIR extension descriptor file内に記述するクラス名を間違えないように注意してください。

ここのクラス名を間違ったばかりに、私は数週間悩みました。ここのクラス名が間違ってても実行時には何もエラーが出ません。なので、何が原因でネイティブコードが呼ばれないのか、非常に悩むことになります。

SWCの作り方が悪いのか?JARの作り方が悪いのか?あるいは、ANEなのか、と。ここに解説してある手順でapkを作成したのに実行時に動作しない場合は、ここを一度疑ってみてください。

あと、いちいち上記手順を手で打ち込んで実行するのは手間なので、itozさんのblogを参考に自動化するスクリプトをantか何かで作った方がいいでしょう。

では、良いaneライフを、Good luck!

2011/08/25

Thoughts on Flash vs HTML5

世の中、何事も対立軸で見た方がわかりやすいし、面白いですよね。最近度々起こるFlash vs HTML5論争もそんな感じなのですが、この論争のきっかけ(のひとつ)を作った敬愛するSteve JobsがAppleのCEOの座を辞職することになったので、これを機会に彼のThought on Flashを真似て、Thoughts on Flash vs HTML5として、自分の考えをまとめてみました。

■FlashとHTML5はそもそも競合する技術なのか?
一部のHTML5支持層はHTML5によって今後Flashは不要になると言う。Flashの多くの支持層は、FlashとHTML5はお互いを排他する存在ではなくて、両方をうまく使ってよりよいものを作って行ければ良いと言う。双方にそれぞれの言い分があるようだ。

じゃー、私はどう思っているのか?と言いますと、私はFlashとHTML5は基本的に競合する技術だと思う。確かに両方をうまく組み合わせて使うことを否定はしないけど、HTML5がFlashのポジションを狙っているのは明らかじゃない?

いまはまだリトルリーグと大リーグくらいの力の差はあるのかも知れないけど、HTML5少年もいつかは大リーガーになることを夢見てこれからも練習に励んでいくんだろう。Flashはその頃には更に先に進んでいるんだろうけど、HTML5で多くの人が必要十分だと思う機能はいずれ実現されると思う。

但し、用語に混乱があるような気がする。HTML5と言っても何がHTML5なのか私にはよくわからない。なので、この手の話はFlash vs その他のWeb技術と捉えるようにしている。もっとぶっちゃけると、Flashを無くしたいと思っている人達と、無くしたく無いと思っている人達の論争なんだろうな、と。

■何でそんなにFlashを無くしたいの?
Flashを無くしたい人達は何でそこまでFlashを嫌うんだろうか?幾つかケースを考えてみた。

1) iOSで見れないから
これはわかる。これは他に選択肢が無いもんね。でも、みんながみんなiOSを使っているわけじゃないんだし、実はFlashを見られない人よりもHTML5を見られない人の方が多いらしいよ?いまんとこね。

2) オープンソースじゃないから
Flash Playerがオープンソースじゃないというのは、いまの時代には嫌うに充分な理由になると思う。自分は、Adobeもそのことは充分承知しているが、オープンにすることで互換性の無いPlayerが広まることを恐れているのでは無いかと勝手に想像している。

だから、Adobeはオープンにしない代わりにみんなの為にいろんなプラットフォームやブラウザ間での互換性を保つ為に血の滲むような多大な努力を払っているんだなと思うようにしている。

まぁ、オープンにしてほしいけどね。

3) プラグインを入れるのが嫌だから
自分もプラグインを入れると何となく不安定になるんじゃないかというイメージは持っているので、なるべくプラグインは入れたく無いという気持ちはよくわかりますし、実際、必要だと思う最低限のものしか入れないようにしてます。でも、常用のブラウザ(Chrome)にはデフォルトでFlash Playerのプラグインが入るようになったんですよ・・・

4) 過去に何か嫌な思いをしたから
過去に糞重いFlashサイトを開いてしまって、すごく迷惑だった?あるいはいきなり大音量が出て恥ずかしい思いをしたとか?何でもそうですけど、一度失った信用を取り戻すというのは大変なことですよね。これに関しては、私から言えることは何もありません。

ただ、Flashが流行り始めたあの頃と違って、いまはそんなにひどいサイトはあまり見かけないと思うんですけどねー。

5) ちょっとした出来心
HTML5によって以前よりもインタラクティブなサイトがFlashを使わなくても作れるようになったというのは歴然たる事実だと思う。だから、Flashイラネとか言ってみたらちょっと受けるかな?とか、ちょっとした出来心で言ってしまったってのが本当のところじゃないのかな?

■FlasherはFlashが無くなったら困るの?
じゃー仮にFlashの無い世界がやって来たとして、Flasherは困るのだろうか?実はそんなに困らないんじゃないのかなぁ?と思ってます。むしろFlashを毛嫌いして、インタラクティブなUIやコンテンツをあまり作ってこなかった人達の方が、HTML5の時代になって、そういうコンテンツを求められた時に困るのでは無かろうか?

AdobeもHTML5対応のツールを今後積極的に出していくと思うし、Edgeを見てみても、それは現在のFlash IDEの使い勝手をある程度踏襲したものになるだろう。であれば、極論すれば、Flasherに取っては出力フォーマットがFlashかHTML5の違いでしか無いのだ。

だからHTML5の時代が来ても、インタラクティブなUIや演出に長けたFlasherの仕事は減ることは無く、むしろ増える方向に行くのでは無いだろうか?HTML5にはまた違ったKnowHowが当然求められるだろうが、Flashで一回乗り越えた人達の方が、いろいろと鼻は効くような気がする。

それに、最終的にAdobeはFlash IDEでFlashコンテンツを作っても、プラグインが無いとHTML5にフォールバックするようなコンテンツを作れるようにするでしょ?それは絶対間違いないでしょ?だからHTML5派の人もFlashを使えるようになってても損はしないと思うけどな。

■まとめ
個人的にはHTML5がFlashを駆逐すると言うにはまだまだ時期尚早だと思うし、現実解としてのFlashは今後もしばらく、というかずっと使われることになると思う。だからと言って安泰というわけでも無く、ある領域に置いてはHTML5にその座を譲ることになるのであろう。

だけど、そんなことはどうでもいいことじゃないだろうか?正直、HTML5とFlashのどちらが明日生き残ろうが、大した問題では無い。そんなことより、大好きなあの子に今日フラれるかも知れないことの方がよっぽど重要な問題だよね。

2011/06/20

Flasherの為のRenderScript入門

■RenderScriptとは?
RenderScriptはAndroid OS3.0から導入された、ハイパフォーマンスな3Dグラフィックスのレンダリングや演算をC言語(C99の構文)で記述できるAPIです。

これまでも、ハイパフォーマンスなレンダリングを行う手段として、OpenGLをNDKで直接叩くという方法がありましたが、RenderScriptはLLVMで一旦中間コードにコンパイルされたものがアプリケーションに付随され、実行時にそれぞれの環境向けに最適化されたマシンコードに更にコンパイルして実行するという仕組みになっております。

その結果、使用しているCPUやGPUの種類によらず、同一のソースコードでそれぞれの環境に置いて効率の良いパフォーマンスを発揮しますが、当然のこととして、特定の環境向けにカリカリにチューニングされたOpenGLのパフォーマンスには及びません。

ただ、iPhoneと違って、様々なプラットフォーム上に展開しているAndroid OSのデバイスとしては、環境依存を吸収する手段として、なかなか面白い仕組みでは無いでしょうか?

■RenderScriptシステムのレイヤー構造
RenderScriptのシステムは、以下の3つのレイヤーから構成されます。

・Native RenderScript layer
このレイヤーはレンダリングや演算の為のRenderScriptそのものです。上に書いたように、C言語の構文で記述しますが、 RenderScriptは汎用的なCPUのみならず、GPU上でも実行する場合もあり得るので、標準的なCのライブラリーがすべて使えるわけではありません。

Native RenderScriptライブラリーで提供されている主な機能は下記。
  1.  膨大な数の演算関数
  2. ベクターや行列等の基本データ型に変換するルーチン
  3. ログ取得の為の関数
  4. グラフィックスのレンダリング関数
  5. メモリー領域確保の為の関数
  6. 2元、3元、4元ベクトル等の、RenderScriptシステムをサポートするデータ型や構造
・Reflected layer
Reflected layerは、AndroidVMからnative RenderScriptコードにアクセスする為の レイヤーで、Androidのビルドツールが自動生成します。その為、Reflected layerは、Android frameworkからRenderScript内の関数や変数にアクセスする為のエントリーポイントを提供します。

・Android framework layer
Android framework layerは、RenderScript APIや通常のAndroid framework APIから構成され、あなたのアプリケーションのActivityのライフサイクルやメモリーの管理などをします。また、このレイヤーで、Reflected layerを介して、ユーザーの操作をnative RenderScriptのコードに関連づけたりもします。

と、かなり前置きが長くなりましたが、詳しくはここのドキュメントを読んでみてください。Flasher的にはC/C++で記述し、同様にLLVMでActionScriptに変換するAlchemyを使うのと、ノリは似ているかも知れませんね。

今回、RenderScriptを使ってFlashでよく使われるParticleのデモを実装してみたいと思いますが、題材としてWonderflの重力マウス(さらに軽量化してみた)を使用したいと思います。

■重力マウスをRenderScriptに移植
重力マウスを移植するにあたって、以下の4つのファイルを記述します。
Gravity.javaGravityアプリのActivityを記述
GravityView.javaRenderScript用のSurfaceViewを記述
GravityRS.javaRenderScript用のエントリーポイントクラスを記述
gravity.rsRenderScriptのコードを記述

Gravity.java
package com.android.sample;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class Gravity extends Activity {
    private GravityView mView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        mView = new GravityView(this); // RSSurfaceViewの作成
        setContentView(mView);
    }
}
特に何も難しいことはしていません。Activityの中で、アプリケーションで使用するViewを設定していますが、今回はRSSurfaceViewを継承したGravityView(後述)を作成してます。

GravityView.java
package com.android.sample;

import android.renderscript.RSSurfaceView;
import android.renderscript.RenderScript;
import android.renderscript.RenderScriptGL;

import android.content.Context;
import android.view.SurfaceHolder;
import android.view.MotionEvent;

public class GravityView extends RSSurfaceView {

    public GravityView(Context context) {
        super(context);
    }

    private RenderScriptGL mRS; // グラフィックス出力の為にスクリプト等
                                // を付与するコンテクスト

    private GravityRS mRender;  // エントリーポイントクラス

    // Surfaceの構成が変わると呼ばれるハンドラー
    public void surfaceChanged(SurfaceHolder holder, int format,
                               int w, int h) {
        super.surfaceChanged(holder, format, w, h);
        if (mRS == null) {
            // グラフィックスのピクセルフォーマットを指定する為のクラス
            RenderScriptGL.SurfaceConfig sc
                = new RenderScriptGL.SurfaceConfig();
            mRS = createRenderScriptGL(sc);
            mRS.setSurface(holder, w, h); //osのsurfaceをバインド

            // エントリーポイントクラスを作成
            mRender = new GravityRS();
            mRender.init(mRS, getResources(), w, h); // 初期化
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        // 後始末
        if (mRS != null) {
            mRS = null;
            destroyRenderScriptGL();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev)
    {
        // エントリーポイントクラスにタッチした座標、指圧と
        // IDの情報を渡す
        // IDはマルチタッチがサポートされている場合に、
        // タッチした指を識別する為のID
        mRender.newTouchPosition(ev.getX(0), ev.getY(0),
            ev.getPressure(0), ev.getPointerId(0));        
        return true;
    }
}
RenderScriptでレンダリングした内容を表示する為のSurfaceViewクラスです。

surfaceChanged()メソッド内でRenderScriptのコンテキストを生成し、Surfaceをバインドしています。スクリプトのバインディングは、後述するエントリーポイントクラス(GravityRs)の方で行なっています。

また、タッチイベントが発生した際も、エントリーポイントクラスに座標等のタッチに関連する情報を渡します。このように、ユーザーの操作によって発生したイベントは基本的にエントリーポイントクラスに情報を渡して、エントリーポイントクラス側で処理をしてもらいます。

GravityRS.java
package com.android.sample;

import android.content.res.Resources;
import android.renderscript.*;

public class GravityRS {
    public static final int PART_COUNT = 50000; // 総パーティクル数

    public GravityRS() {
    }

    private Resources mRes;
    private RenderScriptGL mRS;      // レンダリングのコンテクスト
    private ScriptC_gravity mScript; // スクリプトファイルへの
                                     // エントリークラス

    // 初期化関数
    public void init(RenderScriptGL rs, Resources res,
                     int width, int height) {
        mRS = rs;
        mRes = res;

        // GLSLコードを用いないシンプルなフラグメントシェーダーを作成
        ProgramFragmentFixedFunction.Builder pfb
            = new ProgramFragmentFixedFunction.Builder(rs);

    // バーテックスプログラムから指定された色を使用する
        pfb.setVaryingColor(true);

        // フラグメントシェーダーをレンダリングコンテクストにバインド
        rs.bindProgramFragment(pfb.create());
        
        // スクリプト内のPoint構造体×パーティクル数の分だけ
        // メモリー領域を確保する
        ScriptField_Point points = new ScriptField_Point(mRS,
                                                         PART_COUNT);
        
        // RenderScriptで表示する幾何学データのコンテナを作成する
        // オブジェクト
        Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);

        // pointsを頂点データとしてオブジェクトに追加
        smb.addVertexAllocation(points.getAllocation());

        // データの種類を点座標に設定
        smb.addIndexSetType(Mesh.Primitive.POINT);

        // コンテナを作成
        Mesh sm = smb.create();

        // スクリプトファイルのエントリークラスを生成
        mScript = new ScriptC_gravity(mRS, mRes, R.raw.gravity);

        // スクリプト内のpartMeshにMeshをセット
        mScript.set_partMesh(sm);

        // pointsとスクリプト内のpointをバインド
        mScript.bind_point(points);

        // レンダリングコンテクストにスクリプトをバインド
        mRS.bindRootScript(mScript); 
    }

    // タッチ情報のアップデート
    public void newTouchPosition(float x, float y, float pressure,
                                 int id) {
        mScript.set_gTouchX(x); // スクリプト内のgTouchXにX座標をセット
        mScript.set_gTouchY(y); // スクリプト内のgTouchYにY座標をセット
    }
}
一見、複雑なことをやっているようですが、まずフラグメントシェーダーの設定し、それから座標データを格納するメモリー領域の確保をしてます。その後、ビルドツールで自動生成されるエントリーポイントのクラスをインスタンス化して、スクリプト内の変数やポインターと確保したメモリー領域の関連付けを行ってます。

そして最後に、レンダリングコンテクストにスクリプトをバインドして実行、という感じでしょうか?

gravity.rs
#pragma version(1)
#pragma rs java_package_name(com.android.sample)
#pragma stateFragment(parent)

#include "rs_graphics.rsh"

// staticな変数はエントリーポイントが生成されない
static int initialized = 0;

rs_mesh partMesh; // 描画するデータのコンテナ

// タッチ座標
float gTouchX = 0.f; // X座標
float gTouchY = 0.f; // Y座標

// パーティクルの構造体
typedef struct __attribute__((packed, aligned(4))) Point {
    float2 delta;
    float2 position;
    uchar4 color;
} Point_t;
Point_t *point;

// パーティクルの初期化
void initParticles()
{
    // データサイズを取得
    int size = rsAllocationGetDimX(rsGetAllocation(point));

    float width = rsgGetWidth();   // サーフェイスの幅
    float height = rsgGetHeight(); // サーフェイスの高さ

    uchar4 c = rsPackColorTo8888(0.9f, 0.0f, 0.9f); // 色

    Point_t *p = point;
    for (int i = 0; i < size; i++) {
        p->position.x = rsRand(width);  // 乱数でX座標をセット
        p->position.y = rsRand(height); // 乱数でY座標をセット
        p->delta.x = 0;
        p->delta.y = 0;
        p->color = c;
        p++;
    }
    initialized = 1; // 初期化完了
}

/*
 * root()は描画する毎に呼ばれる
 */
int root() {
    // 初回実行時に初期化
    if (!initialized) {
        initParticles();
    }

    float width = rsgGetWidth(); 
    float height = rsgGetHeight();

    // 指定色でレンダリングサーフェイスをクリア
    rsgClearColor(0.f, 0.f, 0.f, 1.f);
    
    int size = rsAllocationGetDimX(rsGetAllocation(point));

    Point_t *p = point;
    for (int i = 0; i < size; i++) {
        float diff_x = gTouchX - p->position.x;
        float diff_y = gTouchY - p->position.y;
        float acc = 50.f/(diff_x * diff_x + diff_y * diff_y);
        float acc_x = acc * diff_x;
        float acc_y = acc * diff_y;
        p->delta.x += acc_x;
        p->delta.y += acc_y;
        p->position.x += p->delta.x;
        p->position.y += p->delta.y;
        p->delta.x *= 0.96;
        p->delta.y *= 0.96;
        if (p->position.x > width) {
            p->position.x = 0;
        } else if (p->position.x < 0) {
            p->position.x = width;
        }
        if (p->position.y > height) {
            p->position.y = 0;
        } else if (p->position.y < 0) {
            p->position.y = height;
        }
        p++;
    }    
 
    rsgDrawMesh(partMesh); // 座標データ列の描画
    
    return 1; // おおよそ1ms後に再描画
}
最後にいよいよRenderScriptの本体です。

まず、Point構造体がパーティクルのデータ構造を構成しており、初回実行時だけ、initParticles()関数内で、パーティクルの座標や色のデータの初期化を行います。

そして、root()関数が描画毎に呼ばれる関数で、Flasher的にはenterFrameのイベントハンドラーのようなものと思えば、理解がしやすいでしょうか?この中のfor文で各パーティクルの座標データをアップデートしております。ここのコードは重力マウスのコードをほぼ、そのまま丸パ◯リ(笑)

ActionScriptでは、動作スピードを上げる為に、リンクリストを形成しておりましたが、ここではリンクリストは使用しないで、単純に構造体のポインターをfor文で要素の数だけ回すという処理になってます。

パーティクルの座標データの更新が終わったら、rsgDrawMesh()という関数で、コンテナ内のデータを元に描画を行います。

最後に、このファイル中に出てきたRenderScript関連の関数をまとめておきます。
rsGetAllocation()VM側で確保したメモリー領域を返す
rsAllocationGetDimX()メモリー領域のX方向の大きさを返す。今回、データは1次元の配列なので、要素数を返すことと同じか?
rsgGetWidth()サーフェースの幅を返す
rsgGetHeight()サーフェースの高さを返す
rsPackColorTo8888()R, G, B値から色コード(8888形式)を生成
rsRand()乱数値を生成
rsgDrawMesh()コンテナのデータを元に描画

■RenderScriptのパフォーマンス
RenderScriptを使うことで、どれくらいのパフォーマンスが出たのでしょうか?PC上では重力マウスは、楽に60fps出ていますが、手持ちのXOOMのブラウザ経由では、20fpsほどしか出ません。

今回、RenderScriptにはfpsを計測する機能を実装していないので、厳密にはどれくらいのフレームレートが出ているのかはわかりませんが、 フルスクリーン(解像度で4倍以上)で、尚且つパーティクルの数を50000に増やしても、目視で30fpsはゆうに出ているように感じました。

なので、少なく見積もっても5倍以上の性能差はありそうです。モバイル版のFlash Playerに早くStage3Dが搭載されることが待たれますね。

実際のアプリケーションの動作の動画を以下に貼りつけておきます。


■まとめ
難しいことは全て理解しなくとも(私も半分くらいしか理解できてない)、上記ファイルをテンプレートに、RenderScriptファイル中のfor文の中身(パーティクルの動作をつけている部分)を適当に書き換えれば、簡単に遊べると思いますので、腕に覚えのあるFlasherの方に是非お試しいただければと思います。

まぁ、遊ぶにはAndroid 3.xの実機が必要にはなりますがね・・・(^_^;

2011/04/02

てら子14 GoogleAPI

ちょっと遅くなりましたが、東京てら子14 GoogleAPIで発表した内容を公開します。

当日は時間が足りなくて、かなり駆け足でほとんど何も説明の無い状態でしたので、じっくり資料をご参照いただき、ご不明な点がございましたら、twitterにでも質問を投げてください。

・東京てら子14発表資料 Google URL短縮(リンク)

また、ソースコードはSpark Projectの方にアップしておきました(リンク)。
 
コミットしたの1年振りくらいかな(汗