AndARのソースコードを確認したところで、ここからは別の3Dモデルを表示してみましょう。
実際に、3Dモデルを表示したい場合は、サンプルのような立方体ではなく複雑なデータを表示したい場合が多いのではないでしょうか。
複雑なデータをOpenGL ESを使ってコーディングしていくのは大変です。一般的には、objファイル(WaveFront形式)などの3Dモデルデータを読み込ませる方法が多いと思います。
3Dモデルデータを読み込ませて3Dモデルとして表示するには、3DモデルデータをパースしてOpenGL ESを使ってレンダリングできるようにする必要がありますが、残念ながらAndARには3Dモデルの読み込みやパースする処理などはありません。
そこで、これらを実現するために、AndARModelViewerのソースを参考に実装してみます。
「AndARModelViewer」というのはAndARを利用したアプリで、AndARModelViewerもAndARと同様にソースコードを公開しています。このアプリは、objファイルのパーサを実装しているためobjファイルを読み込んで3Dモデルを表示できます。
このパーサを参考に3Dモデルの読み込みを実装してみます。まず、AndARModelViewerのsrc以下にある以下のパッケージをAndARのsrc以下に配置します。
ここからはソースコードを修正していきます。今回利用したソースコードのリビジョンは199です。
先ほど説明したように、基本的にはCustomActivity、CustomObject、CustomRendererの3ファイルを修正します。
ただし、今回は少ない修正でobjファイルからの読み込みを実現するため、CustomObjectはedu.dhbw.andobjviewer.graphics.Model3Dクラスに、CustomRendererはedu.dhbw.andobjviewer.graphics.LightingRendererクラスに書き換えたとみなしてください。そのため、CustomActivityのみの修正となります。
3Dモデルをobjファイルから読み込ませるためにAndARModelViewerのedu.dhbw.andobjviewer.AugmentedModelViewerActivityのsurfaceCreatedを参考に、CustomActivityにSurfaceHolder.Callbackをimplementsし、surfaceCreatedをオーバーライドします。
モデルの読み込みは、ModelLoader().execute("sofa.obj")で行っています。今回はAndARModelViewerに付属していたsofa.objを表示するため、引数に指定しています。
ModelLoaderはAsyncTaskを使っているため、モデルを非同期に読み込みます。AugmentedModelViewerActivityでは、ModelLoaderを以下のように実装しています。
ただし、ModelLoaderをこのまま実装しても、うまく動作しないので、ソースコードを修正していきます。
まず、「ModelLoader().execute()」にString型の引数を取らせるため、Genericsの1番目の型をStringとし、「doInBackground(Void…… params)」の引数を「doInBackground(String…… params)」に変更します。
次に、Intentからデータを受け取らないように変更します。AndARModelViewerではIntentからtypeとdataを取り出していますが、渡ってくるIntentはないのでコメントアウトして、以下のコードを追加します。
type = TYPE_INTERNAL;
modelFileName = params[0];
「type」は、どこからモデルデータを読み出すかを指定しています。今回はAndroidアプリ内のassets/modelからデータを読み込むために「TYPE_INTERNAL」とします。読み込むデータは、「assets/models/sofa.obj, sofa.mtl, sofa.png」として、AndARModelViewerからコピーして配置します。
「modelFileName」は、3Dモデルデータのファイル名を示しており「ModelLoader().execute("sofa.obj")」の引数で渡されている文字列「sofa.obj」を代入します。
修正したものが以下のコードです。
// private class ModelLoader extends AsyncTask<Void, Void, Void> {
private class ModelLoader extends AsyncTask<String, Void, Void> {
@Override
// protected Void doInBackground(Void... params) {
protected Void doInBackground(String... params) {
// Intent intent = getIntent();
// Bundle data = intent.getExtras();
// int type = data.getInt("type");
int type = TYPE_INTERNAL;
// String modelFileName = data.getString("name");
modelFileName = params[0];
これで、assets/models/sofa.objを読み込めるようになります。objファイルを読み込んだら、以下のメソッドでobjファイルをパースしてModelクラスのインスタンスmodelを作成します。
model = parser.parse("Model", fileReader);
さらに作成したmodelを引数としてARobjcectクラスを継承したModel3Dのインスタンスを作成し、マーカー検出時に3Dモデルを描画するように登録します。以下のメソッドで実現しています。
artoolkit.registerARObject(model3d);
これにより、マーカー検出時にmodel3dのクラスModel3Dのdrawメソッドを呼びます。詳細は割愛しますが、OpenGL ESを利用して3Dモデルを描画します。
検出するマーカーについては、Model3Dのコンストラクタ内の以下のメソッドで検出するマーカーの種類を定義します。
super("model", "barcode.patt", 80.0, new double[]{0,0})
今回利用するマーカーは幅80mmの「barcode.patt」です。
最後に、CustomActivityのonCreateを以下のように修正します。
また、「artoolkit.registerARObject(someObject)」をコメントアウトしたため、try-catchも不要になります。
「LightingRenderer renderer = new LightingRenderer()」は、「CustomRenderer renderer = new CustomRenderer()」のままだと3Dモデルが全体的に暗くレンダリングしてしまうので、AndARModelViewerのrendererのLightingRenderer()メソッドに置き換えます。
さらに、CustomActivityでsurfaceCreatedをオーバーライドしたため、getSurfaceView().getHolder().addCallback(this)でcallbackを再設定しておきます。
後は、適切なパッケージをimportし、R.string.loadingは「res/values/string.xml」にして、以下を追加します。
このように修正することで、objファイルを読み込んで3Dモデルを表示できるようになります。
では、実際にアプリを動かしてみましょう。アプリを起動したらbarcodeマーカー(図6)にかざします。すると、ソファーの形をした3Dモデルを表示していることが確認できると思います(図7)。
これで、別の3Dモデルをマーカー上に表示できました。
が、ここで注意点があります。このサンプルはAndARで読み込み可能なobjファイルの形式を制限しており、objファイルであっても読み込めない場合があります。具体的な制限は以下の通りです。objファイルを読み込む場合には、この点に注意してください。
独自に3Dモデルを作成した場合には、「Blender」というソフトを利用してobjファイルのエクスポートをすると、本アプリに対応する形式で出力できます。うまく表示しない場合は、出力時に上記の制約を満たすように設定を行い、エクスポートしてみてください。
最後に、AndARのメリット・デメリットについてまとめておきます。
AndARのメリットとしてはコアとなるクラスを継承して作成するようになっているため、「CustomActivity」「CustomObject」「CustomRenderer」の3クラスの修正だけでオリジナルの3Dモデルを自由に変更して表示できます。
ソースコードもオブジェクト指向を強く意識しているため読みやすく、ネイティブコードにアクセスするといったコアな部分をラップしているため、設定などの定型的な処理や、マーカー検出や変換行列の計算などの複雑な処理をあまり意識しなくても比較的簡単にマーカー上に3Dオブジェクトを表示できます。そのため、その他のライブラリやサンプルアプリと比較すると扱いやすいと思います。「コアな部分は取りあえず置いて、おいて動かしたい!」という方向きです。
一方、前回紹介したNyARToolkit for Androidはソースを追うことが難しい部分も多く、扱うには慣れが必要だと思います。ただし、処理の流れを確認したい場合には、とても勉強になると思います。
AndARのデメリットとしては複雑なモデルを読み込ませる場合に、大きく手を入れる必要があるという点があります。
今回はAndARModelViewerからobjフォーマットの3Dモデルをパースする処理を持ってきましたが、先に述べたようにobjファイルの特定の形式にのみ対応しているため、汎用的なobjファイルの読み込みや他の形式の読み込みはできません。そのため、複雑なモデルを表示したい場合は、他のライブラリをうまく組み合わせて使うか、自作する必要があります。
もし、すでに独自にパーサなどを保有している場合は、それらを利用することによって比較的少ないコストで3Dモデルを表示できる可能性もあります。
ちなみに、NyARToolkit for Androidでは「min3d」というフレームワークを利用しているので、objファイル以外のファイル形式の3Dモデルも読み込ませることができます。
この辺りは利用するシチュエーションによって、どちらが良いかが変わってくると思いますので、用途に合った方法を適切に選択してください。
ARアプリの作成は、ライブラリやサンプルアプリを利用することで手軽に実現できるようになってきました。ARを実現するためのライブラリは今回のAndARのようなオープンソースのものだけに限らず、さまざまな種類のものが続々と登場してきています。実現したいアプリに合わせて適切なライブラリやサンプルアプリを活用し、オリジナルなARアプリを作成してみてください。
次回は、今回紹介したAndARをベースに3DのモデルをOpenGL ESを利用してアニメーションする手法について、簡単な例を交えて説明します。
Copyright © ITmedia, Inc. All Rights Reserved.