はじめに

ARクラウドとして強力なImmersalの検証を行います。
今回はサンプルプロジェクトを実際に動かしていきます。

導入までは下記ドキュメントの手順通りです。
特に詰まるポイントもなかったので割愛します。

Getting Started


バージョン、環境情報

Unity 2019.4.8f1
Immersal SDK 1.7.0
Immersal Mapper 1.7.0

撮影時の天候 曇り


マップ作製

下記ドキュメントの注意点に従ってマップを作成します。
How To Map

実際に作成したマップデータをglbファイル形式で出力したものがこちらです。

このマップ作成においては15枚しか撮影を行っていません。
マップ作成を正しい撮影方法で行えば、はっきりとした特徴点抽出が行えます。

このglbファイルは自前で変換の処理を挟まなくとも
マップ作成後自動的に出力され、開発者ポータルにアップロードされます。


サンプルにマップを埋め込む

今回利用するサンプルシーンは下記です。
Assets/ImmersalSDK/Samples/Scenes/ContentPlacementSample

先程作成したマップのbytes形式のデータを
ポータルからダウンロードしてサンプルプロジェクトの中にインポートします。
ちなみにこちらの点群データはたったの220KBでした。


下記画像のMapFileにインポートしたマップデータを
アタッチすれば準備完了です。


実機デモ

実機でのデモ動画になります。

デモの内容は下記です。
①特徴点からマップのマッチング処理開始
②マップ認識後、3D空間にダイヤモンドを配置
③端末内にダイヤモンドの位置情報を保存
④アプリを再度立ち上げた際にダイヤモンドを再配置


非常に精度が高いことが見て取れます。


マップの再認識

一時的にマップから離れて
再度認識合わせを行った場合の挙動を確認してみました。

約20m程歩行してから再度認識位置に戻っています。

マップの認識範囲にカメラの画角が収まった瞬間に
正確に位置合わせが行われました。


サンプルシーン上の処理

サンプルシーン上で行われている処理について簡単に解説します。

マップを内包する1つのAR空間がオブジェクトとして定義されています。

ダイヤモンドはAR空間の子オブジェクトとして空間に生成されます。
ここまでの説明を図に落とし込むと下記画像のような状態です。


今回のサンプルシーン内のコードを見るとより理解が深まります。

下記はダイヤモンドの配置に関する
ContentStorageManagerクラス内のコードです。

public void AddContent()
{
    Transform cameraTransform = Camera.main.transform;
    GameObject go = Instantiate(m_ContentPrefab, cameraTransform.position + cameraTransform.forward, Quaternion.identity, m_ARSpace.transform);
}

public void SaveContents()
{
    m_Positions.Clear();
    foreach (MovableContent content in contentList)
    {
        m_Positions.Add(content.transform.localPosition);
    }
    m_Savefile.positions = m_Positions;

    string jsonstring = JsonUtility.ToJson(m_Savefile, true);
    string dataPath = Path.Combine(Application.persistentDataPath, m_Filename);
    File.WriteAllText(dataPath, jsonstring);
}

public void LoadContents()
{
    string dataPath = Path.Combine(Application.persistentDataPath, m_Filename);

    try
    {
        Savefile loadFile = JsonUtility.FromJson<Savefile>(File.ReadAllText(dataPath));

        foreach (Vector3 pos in loadFile.positions)
        {
            GameObject go = Instantiate(m_ContentPrefab, m_ARSpace.transform);
            go.transform.localPosition = pos;
        }
    }
    catch (FileNotFoundException e)
    {
        Debug.LogError(dataPath + " not found\nNo objects loaded: " + e.Message);
    }
}

AddContentメソッドの中でダイヤモンドの生成処理を行っています。
AR Space(AR空間として扱われるオブジェクト)の
子階層に配置しているのがわかります。

その後のSaveContentsメソッド内では
ダイヤモンドのローカルポジションをJson形式として保存しています。

LoadContentsメソッドにおいては
再度ダイヤモンドをAR Spaceの子階層に配置し、
先程のJson形式で保存したローカルポジションを適用して
復元しています。

この一連の処理から、ARコンテンツを作成する際には
ARオブジェクトをAR Space(AR空間として扱われるオブジェクト)の
子階層の任意のローカル座標に配置すれば良い
ことがわかりました。

事前に任意の位置に細かく合わせて出現させたい時などは
glbファイルをUnityエディターにインポートして視覚的に配置する、
もしくはAR空間に配置したオブジェクトの座標を記録しておく配置ツールなどを作成するのも良いかもしれません。


まとめ

Immersalは簡単にARコンテンツの開発ができる上に、
精度が高いので、開発者にとって非常に使いやすいツールであると感じました。

Nrealにも対応したようなので
今後スマートグラスのARコンテンツ開発においても
より一層強力なツールとなりそうなので要注目です。