Tech Sketch Bucket of Technical Chips by TIS Inc.

マーカーをタップすると3Dアバターがしゃべって動くARアプリ 3

Pocket

前々回前回 の記事に引き続き、AndARを改造して「マーカーをタップすると3Dアバターがしゃべって動くARアプリ」の解説をします。

今回と最終回の次回を使って、「マーカーをタップしたことを判断するロジック」や「個々の3Dオブジェクトに独自のアニメーションを実装する方法」を、具体的なアプリケーションのソースコードを元に解説します。

なおこの「マーカーをタップすると3Dアバターがしゃべって動くARアプリ」のソースコードは、Github上に公開しています。

https://github.com/tech-sketch/AR_Speaker

ぜひcloneして、このアプリの動作を確認してみてください。


AR_SpeakerActivity

それでは今回は、このマーカーをタップすると3Dアバターがしゃべって動くARアプリの中心となるAR_SpeakerActivityを解説します。

AndARを活用したアプリケーションを作る場合、android.app.Activityではなくedu.dhbw.andar.AndARActivityを継承します。
これにより、

  • カメラプレビューのハンドリング
  • マーカーと対応する3Dモデルの保持
  • マーカー認識と変換行列の計算
  • 3Dモデルのレンダリング

などといった、ややこしい部分をAndARにお任せすることができます。

実際に自分で書くのは、

  1. 起動時にARToolkitへアバターを登録する
  2. Activityがフォアグラウンドへ来た際に、SoundPoolを初期化し音声データを登録する
  3. Activityがバックグラウンドへ回った場合には、SoundPoolを解放する
  4. タッチイベントをハンドリングし、「マーカーの中心あたりがタップされた」場合に各アバターへアニメーションや音声再生処理を委譲する

という処理です。

起動時にARToolkitへアバターを登録する

アプリケーション起動時に、アバターの3Dモデルを登録します。

各アバターを意味する具象クラス( この記事では、 PorlElaine ) をAndARに登録するのですが、この処理にはかなり時間がかかります。そのため登録処理を ModelLoader というAsyncTaskとして切り出し、画面描画と非同期で実行させています。(AsyncTask自身の使い方については、 ココ などを参考にしてください)
登録処理をしている間、メインの描画スレッドにはプログレスダイアログを表示させます。

ModelLoaderのdoInBackgroundでは、アバター(PlayerBase)のリストを受け取り、arToolkitへそのアバターのModel3Dオブジェクトを登録(arToolkit.registerARObject)します。
# アバターの基底クラス PlayerBase 及びその具象クラスの実装については、次回解説します。

全てのアバターの登録が完了した後にonPostExecuteが呼び出されますので、プログレスダイアログを消去します。
また後のタッチイベントハンドリングで用いるために、カメラプレビューの幅と高さ、Displayの幅と高さから、カメラ座標系のX座標/Y座標をスクリーン座標系のX座標/Y座標へ変換する係数を求めておきます。

SoundPoolを初期化し音声データの登録する

アプリケーションがフォアグラウンドに来たタイミングでSoundPoolを初期化(new SoundPool)し、すべてのPlayerの音声をSoundPoolに登録(player.loadSound)します。SoundPoolへ音声データを登録すると、soundIdが得られますので、各アバターは「自分のsoundId」を記憶しておきます。

SondPoolへの音声データの登録も、やはりそれなりに時間がかかりますので、SoundPoolへ「音声データ登録完了時に呼び出されるコールバックリスナ(OnLoadCompleteListener)」を登録しておきます。コールバックを受け取った際には、各アバターへ「このsoundIdの登録が完了したよ」と通知します。これにより、各アバターは自分の音声データの登録が完了したのか知ることができます。

SoundPoolを解放する

SoundPoolは音声データをメモリ上に保持しますので、Androidデバイスのメモリを圧迫します。そのためアプリケーションがバックグラウンドに回った際(onPause)には、SoundPoolを解放(sp.release)してください。

タッチイベントをハンドリング

画面がタップされた(onSingleTapUp)際に、「タップされた位置のスクリーン座標(touchX/touchY)」を取得します。
今回改造したことで、arToolkitには全てのマーカーの位置情報が保持されていますが、この「位置情報」はカメラプレビューの座標系です。そこで起動時に計算しておいたカメラ座標系のX座標/Y座標をスクリーン座標系のX座標/Y座標へ変換する係数を用いて「スクリーン座標系におけるマーカーの位置」を計算し、 スクリーン座標系におけるマーカー位置とタップ位置のズレがTHRESHOLD以下 である場合に いずれかのマーカーがタップされた と判別します。

マーカー情報には位置だけでなくマーカーファイル名も保持されていますので、その名前を取り出して「XXという名前のマーカーがタップされたよ」と全てのアバターへ通知します。
各アバターはその通知をチェックし、「自分のマーカーがタップされた」ことがわかった場合にはアニメーションと音声データの再生を行うのです。

次回は

最終回となる次回は、アバターの基底となるPlayerBase、及び具体的なアバターを定義するクラスについて解説します。

エンジニア採用中!私たちと一緒に働いてみませんか?