tks_yoshinagaの日記

KinectやLeap motion, VRやARなどの技術を使ってやったことのメモとか

ARCoreで検出した水平面にオブジェクトを落とす

1.はじめに

8月末にGoogleからAndroid用ARプラットフォームのARCoreが発表されました。
下記サイトにも書かれているようにARCoreによってマーカーを使わずに端末の位置・姿勢のトラッキングができたり、床やテーブルなどの水平面の検出ができたりします。

ARCore Overview  |  ARCore  |  Google Developers

f:id:tks_yoshinaga:20170919144234j:plain

またSDKも非常にシンプルで、提供されているサンプルを活用すれば画面をタップするだけで空間の好きな位置にオブジェクトを配置するアプリをすぐ実現できます。

Choose Your Development Environment  |  ARCore  |  Google Developers

ところが提供されているサンプルの数は1つのみのため、例えば落下したオブジェクトが床でとどまるような表現をするコンテンツを作る場合には、ある程度プログラムを書く必要ありますが情報が少ないのが現状です。(2017/9/19現在)

 という訳で今回は水平面とオブジェクトが相互作用するようなコンテンツの作り方を基本サンプルを編集する形で紹介します。

 

2.準備

詳細は公式チュートリアル に記載されていますが主要なものを挙げると下記の通り。
・Unity 2017.2 Beta 11
Android SDK version 7.0 (API Level 24)
Visual Studio 2017
SDK Preview for Unity
ARCoreService導入済みのGalaxy S8 G950FD

 
続いてプロジェクトのセットアップ。
(1) Unityを起動しプロジェクトを作成
(2) SDK(arcore-unity-sdk-preview.unitypackage)をダブルクリックして追加
(3) Projectタブを開く
(4) [GoogleARCore]→[HelloARExample]→[Scenes]を開く
(5) HelloARをダブルクリック(本記事ではこのサンプルを編集)

f:id:tks_yoshinaga:20170919150014j:plain

あとは公式チュートリアルのConfigure the build settings以降の手順を参照して実行し、実機で動くことを確認。

3.開発

まず衝突判定をするため床オブジェクトにコライダー(Collider)を追加します。
(1) [GoogleARCore]→[HelloARExample]→[Prehabs]を開く
(2) TrackedPlaneVisualizerをクリック
  ※平面を構成する多角形の頂点の最新情報を受け取って可視化するプレハブ
(3) Inspector内の[Add Component]をクリック
(4) [Physics]→[MeshCollider]の順にクリック

f:id:tks_yoshinaga:20170919152659j:plain


続いてコードを編集していきます。
(5) [GoogleARCore]→[HelloARExample]→[Scripts]を開く 
(6) TrackedPlaneVisualizer.csを開く
      ※平面可視化に関する実際の挙動を記述するスクリプト
(7) _UpdateMeshWithCurrentTrackedPlaneメソッドを探す

ソースコードをよく読めばわかりますが、このメソッドでは多角形に近似された平面の外周の点(下図の点0-3)を用いて三角形の集合を作成し、それにメッシュ状のテクスチャを貼り付けて可視化を行っています。その際、メッシュの境界をボカすために内側の点も作成(下図の点4-7)して外側から内側に向けて透過度の変化をつけています。※実際は四角形とは限らない

f:id:tks_yoshinaga:20170919155147j:plain

細かいことはさておき、このメソッドにより平面が三角形の集合に近似されているのでこの形状情報をコライダーに反映させれば、仮想オブジェクトと床などの平面との衝突が表現できます。
具体的には下記を参考に_UpdateMeshWithCurrentTrackedPlaneメソッドの最後に2行のコードを追加するだけ。※この時、コライダーのsharedMeshに一旦nullを代入しないとうまくいかない。

続いて画面タップに合わせて立方体を飛ばします。ちなみにこのサンプルでは画面タップ時の挙動はHelloARController.csに記述されているので、これを編集します。

(8) [GoogleARCore]→[HelloARExample]→[Scripts]を開く 
(9) HelloARController.csを開く
(10) Updateメソッドをコメントアウト
(11) 代わりに下記コードをコピペ
オリジナルとの違いはUpdateメソッドの後半、タップしたあとの記述。もともとは箇所にAndy(Androidのマスコット)を置いていましたが、それに代わってGameObjectの立方体(cube)を生成したあとにAddForceで飛ばしています。

4.まとめ

上記を実機にインストールすれば冒頭で載せた動画のように、画面をタップすると立方体が発射され地面でとどまるはずです。ちなみに自分がこのサンプルを作った後、ほかにサンプルがないものかと思って検索したところ、UnityListというサイトにも同様のコードが上がっていました。ソースコードを見たところ本記事と同様に三角形の頂点情報をコライダーに代入していました。また記述もシンプルなのであちらを使っても良いかと思います。ただしサンプルコードもいつまでも提供されている保証はありません。そんな時は本記事が、公式で提供されているコードの何処をいじれば良いかを考えるためのヒントになれば幸いです。

個人的にはSDKで提供されていない壁の認識やTangoで提供されていたAreaLearningも実装したいなあ。


[おまけ]
趣味でARCoreやGoogle Tangoで色々開発して遊んでいるのでAR開発に関するご相談にも乗れそうなので色々と情報共有ができればと思います。