OculusQuestとRealsenseを接続してPointCloudを見る


#はじめに
この記事は[Unityゆるふわサマーアドベントカレンダー 2019 #ゆるふわアドカレ](https://qiita.com/nkjzm/items/7c933bb5c772a0b75512)
26日目の記事です。最近KinectやRealsenseのPointCloudをUnityで見るものを作るのにハマってまして、今回はOculusQuestでRealsenseのPointCloudを見る為の方法を記事にしました。

# 概要
LibrealsenseのIssuesでUnity WrapperにAndroid用のaarライブラリを入れただけという凄く簡単そうな方法でOculus QuestとRealsenseD435iを接続してPointCloudが見れたという投稿があったので自分の環境でも試してみる事にした。
https://github.com/IntelRealSense/librealsense/issues/4155

# 必要なもの
* OculusQuest 
* RealsenseD415 or RealsenseD435
* USB3 -> USBtypeC変換ケーブル

# 動作環境
Windows10
Unity2019.1.13f1
LibRealsense v2.24.0

# aarファイルビルド
aarライブラリをLibRealsenseのソースをビルドして作ります。
やり方は以下の公式のドキュメントを参考にAndroidStudioで行います。
https://github.com/IntelRealSense/librealsense/blob/master/wrappers/android/readme.md

一点ドキュメント通りに行かない場所があって、Gradle Taskのlibrealsense-->build-->assembleReleaseでビルドするとエラーでビルド失敗します。色々試してみて、librealsense-->build-->buildDependentsでビルドするとaarファイルが何故か出来る事が確認できました。

ビルドが成功すると
\librealsense\wrappers\android\librealsense\build\outputs\aar
にlibrealsense.aarが生成されます。

# Unity環境
UnityでOculusQuestをビルド出来る環境と、Realsenseが動く環境を準備します。

## OculusQuest
Oculus公式のページを見ながら環境設定します。
https://developer.oculus.com/documentation/quest/latest/concepts/book-unity-gsg/#oculus-integration-for-unity

## Realsense環境設定
下記ページのLatest releaseのAssetsから以下のファイルをダウンロードします。
https://github.com/IntelRealSense/librealsense/releases

* Intel.RealSense.SDK-WIN10-***.exe
* Intel.RealSense.unitypackage

Intel.RealSense.SDK-WIN10を実行しインストールするとRealsenseSDKの環境一式がインストールされると、
C:\Program Files (x86)\Intel RealSense SDK 2.0\bin以下にRealsenseSDKのdll一式があります。これは後でUnityの環境に持っていきます。

* Intel.Realsense.dll
* realsense2.dll

Intel.RealSense.unitypackageはRealsenseのUnityWrapperが入っています。これを適当なプロジェクトに展開しAssets / RealSenseSDK2.0 / Plugins以下にコピーします。加えて、ビルドしたaarライブラリも同フォルダに移動します。

## AndroidのUSB接続、カメラ接続を承認する
下記スクリプトをシーン上のどれかのGameObjectにアタッチします。このスクリプトはAndroid(Quest)がRealsenseのカメラを使う承認と、USB接続の承認をとります。これをしないとQuestからRealsenseを起動できません。

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AndroidPermissions : MonoBehaviour
{
#if UNITY_ANDROID && !UNITY_EDITOR
    void Awake()
    {
        if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.Camera))
        {
            UnityEngine.Android.Permission.RequestUserPermission(UnityEngine.Android.Permission.Camera);

        }

        using (var javaUnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (var currentActivity = javaUnityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
        using (var rsContext = new AndroidJavaClass("com.intel.realsense.librealsense.RsContext"))
        {
            Debug.Log(rsContext);
            rsContext.CallStatic("init", currentActivity);
        }
    }
#endif
}
```

# QuestとRealsenseを接続
Quest,Realsesne双方がTypeCポートなので、TypeC <-> TypeCケーブルか、TypeC->USB3  USB3->TypeC変換ケーブルでお互いを接続します。

# QuestビルドしてPointCloudを見る。
UnityWrapperのPointCloudDepthAndColorシーンかPointCloudProcessingBlocksシーンでPointCloudを見る事が出来ますので、これをビルドしてみます。ビルドする前に、このシーン中のGameObjectのどれかに上記のAndroidPermissionsスクリプトを忘れずにアタッチします。

また、RealsenseはIL2CPPでビルドすると動かないのでMonoビルドでビルドします。Questにインストールした後に起動すると、アプリ起動時にUSBの接続許可を求めるダイアログが出現するのでこれをOKするとPointCloudを見る事が出来ます。PointCloudProcessingBlockシーンをQuestから見た結果が以下のようになります。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/Realsense?src=hash&amp;ref_src=twsrc%5Etfw">#Realsense</a> <a href="https://twitter.com/hashtag/OculusQuest?src=hash&amp;ref_src=twsrc%5Etfw">#OculusQuest</a><br>OculusQuestにRealsenseD435を繋げて点群見る事が出来た。<br>基本librealsenseのissueにあった方法をトレースしただけでNativePluginとか作らずにUnityでビルドして普通に動いた。<a href="https://t.co/1JXF6qOhMC">https://t.co/1JXF6qOhMC</a> <a href="https://t.co/VPtAWAZx0m">pic.twitter.com/VPtAWAZx0m</a></p>&mdash; unagi (@UnagiHuman) <a href="https://twitter.com/UnagiHuman/status/1142710866409738241?ref_src=twsrc%5Etfw">June 23, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

# サンプルプロジェクト
githubにOculusQuestでPointCloudが見れる状態のプロジェクトを用意しました。OculusIntegration無しの一番シンプルな状態です。PointCloudDepthAndColorシーンをビルドしてQuestにインストールして下さい。環境設定の参考になると思います。
https://github.com/unagiHuman/unityRealsenseQuest

# おまけ。VFX GraphでPointCloudが見れるかどうか試してみて失敗した話。
keijiro神がRealsenseのPointCloudをVFXGraphで見る事のできるプロジェクトを公開してます。これをQuestでも見たいと思い試してみました。
https://github.com/keijiro/Rsvfx

## VFX GraphをQuestで動かそうと試行錯誤してみた軌跡
VFX GraphがQuestで動くかどうかを色々試してみましたが、結果としてはダメでした。
試行錯誤した結果としては、

* Unity2019.1.13、VFX Graph preview 5.16.1、LWRP環境
    * ⇒VFXGraphのパーティクルが縦に無限にストレッチして見えてしまう。
* Unity2019.3.0a12、VFX Graph 7.0.1 LWRP環境 (VFXGraphのpreviewが外れてた！)
    * ⇒そもそも正常にアプリが起動しない。

Unit公式のissuetrackerではVFX GraphがAndroidの機種によっては動かないとの報告があって、どう頑張ってもQuestでは上手く動かないのかも。
https://issuetracker.unity3d.com/issues/lwrp-vfx-graph-projects-have-visual-artifacts-when-viewed-with-certain-mobile-gpus

## 代替案
Questでも一応computeShaderとGeometoryShaderは動くので、がんばってGPUパーティクルをVFXGraphバリに綺麗なのを作れば代替にならなくもない。

自分が過去記事で試したGPUパーティクルがQuestでも動くのを確認したので、あとはshader側で頑張って表現すればいけるはずだけど超大変なので、やっぱ公式でVFXGraph Quest対応してくれるのを望む。
https://qiita.com/UnagiHuman/items/dde6c73265436baa4829