ARKitを使ってiPhoneをホロレンズっぽい(透過型 MR)デバイスにする試み

ARKitを使ってiPhoneをホロレンズっぽい(透過型 MR)デバイスにする試み

ARKitでiPhoneでもカメラのイメージに仮想物体を置くことができるようになったという話を聞いて、「それなら頑張ればVRメガネ使って、ホロレンズみたいな擬似MRデバイスが実現できるのでは?」と思い試してみた。

カメラ画像をそのまま画面左右に配置してVRゴーグルで除けばそれっぽくなるのでは?と思ってたが、結果として意外とカメラの歪みとか、現実との表示のずれ(目線とカメラの位置が厳密に一致しないため?)等でVR酔い(MR酔いと呼ぶべきか?)しそうなアプリとなってしまった。もっともUnity側でカメラの角度を調整したりして、より現実に近づけることはできるかもしれない。

あと当然だが、ホロレンズほど現実空間に仮想物体を張り付かせるようなことは難しそう。またAirTapはもちろん使えない。(手を画像認識してジェスチャー対応させるとかやってみたい気もするが難しそうだし、精度が出なさそうな気がしてならない)

今回試した手順は以下の通り。

環境:

  • Macbook Pro 2017 13inch(Sierra)
  • iPhoneX(実機デバック用)
  • Xcode9.2
  • Unity 2017.2
  • VRゴーグル(iPhoneのカメラを遮蔽しないもの) (注意 ARKit Pluginの要求でUnityのバージョンが5.6.2以上である必要あり。)

手順:

  1. UnityでアセットストアからUnity ARKit Pluginをインポート

  2. Hierarchyで空のオブジェクトを作成、その中にカメラオブジェクトを二つ設置(デフォルトであるカメラをコピーするのでOK)

  3. 2つのカメラの名前を適切に変更、InspectorのCameraで Viewport Rectをそれぞれ図のように変更(表示画面を二つに分割し、iPhone上で二つの画面が並列に表示されるようする) またそれぞれのカメラに「Unity AR Video」,「Unity AR Camera Near Far」をアタッチする。(Clear MaterialはYUVMaterialを設定)

f:id:hygradme:20180205212613p:plainf:id:hygradme:20180205212617p:plain

4.新規C#スクリプトをProject上にで作成、以下を記述する。

参考:http://edom18.hateblo.jp/entry/2017/11/06/081821

なお通常使用するUnityARKitPluginのUnityARCameraManagerは1カメラを対象として設定しないといけないため、 2画面表示する今回の目的ではそのコードを変更をする必要がある。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.iOS;
public class CustomARCamera : MonoBehaviour {

    public Transform target;
    public UnityARAlignment startAlignment = UnityARAlignment.UnityARAlignmentGravity;
    public UnityARPlaneDetection planeDetection = UnityARPlaneDetection.Horizontal;
    public bool getPointCloud = true;
    public bool enableLightEstimation = true;
    public Dictionary<string, ARPlaneAnchorGameObject> planeAnchorMap = new Dictionary<string, ARPlaneAnchorGameObject>();
    public UnityARSessionNativeInterface session;

    void Start(){
        session = UnityARSessionNativeInterface.GetARSessionNativeInterface();
        Application.targetFrameRate = 60;
        ARKitWorldTrackingSessionConfiguration config = new ARKitWorldTrackingSessionConfiguration();
        config.planeDetection = planeDetection;
        config.alignment = startAlignment;
        config.getPointCloudData = getPointCloud;
        config.enableLightEstimation = enableLightEstimation;
        session.RunWithConfig(config);  
    }

    void Update(){
        //UnityARSessionNativeInterfaceから端末の状態を取得
        Matrix4x4 matrix = session.GetCameraPose();

        //設定した2カメラを子に持つゲームオブジェクトのTransformに位置・回転を適用
        target.transform.localPosition = UnityARMatrixOps.GetPosition(matrix);
        target.transform.localRotation = UnityARMatrixOps.GetRotation(matrix);

    }

}

5.Hierarchy上に空のオブジェクトを作成して、InspectorでCustomARCamera.csを追加する。また図のようにTargetを先ほど2で作成した二つのカメラを子オブジェクトに持つゲームオブジェクトのTransformに設定する。

f:id:hygradme:20180205212621p:plain

6.配置したい箱なり、キャラクターなり(私はルーレット)をHierarchyに作成、適当な位置に設置する。

7.(任意)「PlayerSetting」の「Resolution and Presenteation」のOrientationをLandscapeに設定すれば実機でアプリを実行した時の画面の自動回転が回避できる。(同 「XR Settings」の「Virtual Reality Supported」にチェックを入れるでも良さそう)

8.ビルドして、xcodeで実機デバック。iphoneをVRゴーグルにセットし(カメラを隠さないように)頭に装着すれば完成。 f:id:hygradme:20180205212625p:plain

動画: youtu.be

あとなんか気持ち、普通にARKit試した時に比べて、仮想物体の現実空間への張り付き具合が悪い感じがするが、気のせいだろうか?(床があまり認識されてないからか)あるいは何か間違えているのか? 画面が均等でないが、その辺は3.で設定したパラメータを変更すれば均等になるかもしれない。またパラメータは私のiPhoneXかつ手持ちのVRゴーグルに合わせて決めたので、iPhone8とか他のゴーグルの場合、調整が必要かもしれない。

つい最近ARKitが垂直方向の壁等を認識できるようになったという情報が出てきたので、ARKitでできることが増えそうな気がする。iPhone MRデバイス化に今後も期待。