前々回「NyARToolKitでマーカー型ARのAndroidアプリを作る」、前回「NyARToolKit for Androidよりも簡単なAndARとは」と2回に渡り、Android上で動作するオープンソースARライブラリを解説し、オリジナルの3Dモデルを表示するようにカスタマイズを行いました。
ただ、それらの3Dモデルはマーカー上に鎮座しているだけで、ユーザーの操作には一切反応しませんでした。このようなARは、現実世界のユーザーは現実に拡張された3Dモデルを「見ること」しかできない「片想いのAR」といえます。
もし現実世界のユーザーの操作が仮想空間上の3Dモデルへリアルタイムに通知され、3Dモデルが通知された操作に対応して自らの状態を能動的に変化できるならば、「現実世界にいるユーザー」が「仮想世界にいる3Dモデル」とコミュニケートする「両想いのAR」が実現できることになります。
例えば、現実世界のユーザーの動作に反応して踊る仮想アイドルをARで表示する、といったことが可能となるでしょう。
今回はその「両想いのAR」の第一歩として、「モバイルデバイスのタッチ操作に対応してテニスボールがバウンドするAR」を、AndARを用いて実装します。
完成したARのサンプルの動画 |
昨今の3DCGソフトウェアは高性能で、人や動物がリアルに動き回るアニメーション作品を簡単に作成できます。
これらのソフトウェアで作った作品でも、最終的には「ポリゴンとテキスチャで構成された複雑な3Dモデルを、1フレームずつレンダリングする」という操作をしています。しかし、3DCGソフトウェアが複雑な部分をうまく隠ぺいしているため、3Dモデルの複雑な動きをプログラム的に細かく実装する必要はありません。
一方AndroidやiOSの場合、何らかの3Dライブラリを利用しない限り、基本的に3Dモデルの各ポリゴンの頂点座標を1フレームごとに自分で3Dグラフィックスライブラリ(OpenGL ES)に指示しなければなりまん。そのため「人が手足を振って歩く」ような、各ポリゴンの相対位置が時々刻々と変化する複雑なアニメーションを手作業でプログラム的に実装するのは、かなり困難です。
よって今回はシンプルに、「テニスボールが回転しながら飛び跳ねる」というアニメーションを実装します。この場合、各ポリゴンの3D空間内の頂点座標は1フレームごとに変化しますが、各頂点の相対位置は変化しません。このように頂点の相対位置を変化させずに図形の平行移動、回転、拡大・縮小などを行うことを「アフィン変換」と呼びます。
OpenGL ESには3Dモデルの各頂点に対して一挙にアフィン変換を行うための関数が準備されています。これらの関数を適切に利用することで、各頂点の座標を個々に計算しなくても、テニスボールをアニメーションできます。
なお本稿で利用した「テニスボールの3Dモデル」は、「how to make tennis ball in blender」を参考にしてBlender 2.5で作りました。必要であれば、blender形式のファイルやwevefront形式のファイルをダウンロードし利用してください。
Androidの場合、3.0系以降のNyARToolkit for Androidでモデルローダとして採用されている「min3d」というオープンソースの3Dライブラリがあります。
このライブラリを用いれば、事前に定義されたアニメーション情報に従ってレンダリングが行われるため、複雑なアニメーションを行わせることが可能になります。ただし、本稿の範囲を超えるため、今回は利用していません。
OpenGL ESは、iOSやAndroid、SymbianOSなどの携帯電話の組み込みシステムでよく利用されている3Dグラフィックスライブラリです。Android 2.2以降では、OpenGL ES 1.0/1.1/2.0という3つのバージョンが利用できるようになりました。
このOpenGL ESを用いると、仮想的な3次元空間(ワールド座標系)内にさまざまな3Dモデルを配置し、その仮想空間内の「ある位置にあるカメラから見た光景」を切り取って2次元画像化し、スクリーンにレンダリングできます。NyARToolKit for AndroidもAndARも、3Dモデルを適切にスクリーンへレンダリングするために、内部的にOpenGL ES 1.0を利用しています。
OpenGL ESや3Dモデリング自体についての解説は、「AR開発入門」という主題から逸脱してしまうため、本稿では「ワールド座標系内で3Dモデルを平行移動、回転、拡大・縮小する」という必要な部分だけの解説に留めます。
3Dモデリングの詳細については、TISの技術ブログ「3Dプログラミング基礎知識 」などを参考にしてください。
それでは、OpenGL ESで3Dモデルを動かしてみましょう。
「void glTranslatef(float x, float y, float z)」メソッド、もしくは「void glTranslatex(int x, int y, int z)」メソッドを用います。入力値にx軸方向の移動量、y軸方向の移動量、z軸方向の移動量を与えることで、3Dモデルがワールド座標系内で移動します。
例えば原点上にある3Dモデルに「glTranslatef(1.0f, 0.0f, 0.0f)」を適用した場合、(1, 0, 0)の位置に移動します。
「void glRotatef(float angle, float x, float y, float z)」メソッド、もしくは「void glRotatex(int angle, int x, int y, int z)」メソッドを用います。入力値に回転角度、回転軸のx軸成分、回転軸のy軸成分、回転軸のz軸成分を与えることで、ワールド座標系の原点を中心にした回転軸に対して回転角度(ラジアンではなく度)回ります。
例えばある3Dモデルに「glRotatef(30.0f, 0.0f, 0.0f, 1.0f)」を適用した場合、z軸を中心に30度回転します。
「void glScalef(float x, float y, float z)」メソッド、もしくは「void glScalex(int x, int y, int z)」メソッドを用います。入力値にx軸方向の拡大率、y軸方向の拡大率、z軸方向の拡大率を与えることで、ワールド座標系の原点を中心に3Dモデルの拡大・縮小が行われます。
例えば原点にある3Dモデルに「glScalef(2.0f, 0.5f, 1.0f)」を適用した場合、x軸方向に引き伸ばされたような形になります。
上記のような回転、移動、拡大・縮小を行う場合、適用する順番を十分意識する必要があります。
アフィン変換はスタックのように、後から適用した変換から順に実施される性質を持っています。よって「回転してから移動する」「移動してから回転する」のでは異なった結果となります。適用する順序に十分注意してください。
gl.glTranslate(1.0f, 0.0f, 0.0f); gl.glRotatef(30.0f, 0.0f, 0.0f, 1.0f);
gl.glRotatef(30.0f, 0.0f, 0.0f, 1.0f); gl.glTranslatef(1.0f, 0.0f, 0.0f);
次ページでは、AndAR上にテニスボールの3Dモデルを表示して、ピンチアウト/イン操作による3Dモデルの拡大・縮小、タップ操作によるテニスボールの回転&バウンドをコードを交えて解説します。
Copyright © ITmedia, Inc. All Rights Reserved.