UE4でVIVEFocus用のコンテンツを開発をする

[Unreal Engine 4 (UE4) その2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ue4_zwei)の11日目です。

先月(2018年11月)に日本向けにVIVEFocusが販売開始されました。
しかし、まだUE4でVIVEFocusの開発方法に関する情報が日本語向けにはパッと見なかったので、それについて書きます。

## VIVEFocusについて
HTCVIVEを出している、HTCが出したスタンドアロン型のVRHMD。
6DoFのヘッドセット、1つの3DoFコントローラー
また、個人的な使用感等については[こちらのスライド]
(https://www.slideshare.net/naoakiyamaji/vivefocus)の8ページ目以降でも見ていただけると。

##UE4での開発環境を構築する
まずはUE4でVIVEFocus用のコンテンツを開発するのに必要な環境構築をします。
※今回のエンジンバージョンは4.20.3で行っています(SDKの公式ドキュメントには「Now support Unreal Engine version 4.20.0 ONLY.」と記載されています)。
[SDKの公式ドキュメント](https://hub.vive.com/storage/app/doc/en-us/UnrealPlugin/UnrealPlugin.html)

####Android用の開発環境を構築する
VIVEFocus自体がAndroidベースのOSで、UE4からのデプロイ等についても、ベースはAndroidをターゲットにした開発と同じような設定や準備が必要となります。
UE4でのAndroidの開発用環境設定は[公式のクイックスタート](http://api.unrealengine.com/JPN/Platforms/Android/GettingStarted/)を参考にするのが良いかと思います(ここでは記載しません)。

####Pluginの入ったサンプルを取ってくる
[ここ](https://hub.vive.com/en-US/profile/material-download)からSDKをDLできます。
※HTCアカウントにログインしておく必要があります。
WaveSDKの新しいバージョン(WaveSDK-x.x.x.zip)をDLしてきたら、その中にある「plugins/unreal/plugin.zip」を開きます。
「plugin」フォルダの中にUE4用のサンプルプロジェクトデータが一式入っています。
![UE4_VIVEFocus1.png](https://qiita-image-store.s3.amazonaws.com/0/214053/3cd58db0-b42a-f1c2-fe33-debb658dc61a.png)

ただ、サンプルプロジェクトを開く前に、「ThirdParty」フォルダをUE4のインストールフォルダ(デフォルトだとC:/Program Files)内の「\Epic Games\UE_4.20\Engine\Source\ThirdParty」フォルダにコピーし、
その後サンプルプロジェクトを開きます。
![UE4_VIVEFocus2.png](https://qiita-image-store.s3.amazonaws.com/0/214053/608c7520-b37d-0100-6988-f0790b8616bb.png)

####サンプルをデプロイする
プロジェクトの設定等は一通りされているサンプルプロジェクトなので、Android用の設定のみ確認し、パッケージ化できます。
プロジェクト設定の「プラットフォーム」→「Android」→「APK Packaging」にある「プロジェクトはAndroidプラットフォームに対応していません」のところで、「今すぐ設定」を押し、
すぐ下の「Accept SDK License」も押し、表示されるライセンスを確認し、同意します。
![UE4_VIVEFocus3.png](https://qiita-image-store.s3.amazonaws.com/0/214053/f316f737-4e55-4de0-ca68-730fc0ddf818.png)
![UE4_VIVEFocus4.png](https://qiita-image-store.s3.amazonaws.com/0/214053/8877b1e4-a278-3037-6c51-58ad30b40744.png)
![UE4_VIVEFocus5.png](https://qiita-image-store.s3.amazonaws.com/0/214053/4dd9814c-da67-a272-d764-0a45174f8e36.png)

これでこのプロジェクトの設定はできたので、パッケージ化します。
「ファイル」→「パッケージ化」→「Android」→「Android(ASTC)」を選択して、パッケージ化を行います。
![UE4_VIVEFocus6.png](https://qiita-image-store.s3.amazonaws.com/0/214053/61def8ea-1cb9-d80f-e970-0061ae36bd10.png)
![UE4_VIVEFocus8.png](https://qiita-image-store.s3.amazonaws.com/0/214053/3dcd5445-3656-d4e7-8925-de2a77c7abbe.png)

パッケージ化できたら、実機に転送します。
転送方法は今までのAndroid端末と同じ流れになります。
![UE4_VIVEFocus10.png](https://qiita-image-store.s3.amazonaws.com/0/214053/89478949-7712-6bbe-2913-859dee26fc61.png)

実機ではこんな感じになっています。
![Screenshot_20181210-195134.png](https://qiita-image-store.s3.amazonaws.com/0/214053/c10e8eff-91fc-b511-96dc-e5ebd35eab3b.png)


####プロジェクトの設定について
実機のデプロイが確認できたので、次は新規でプロジェクトを作って確認しようと思います。
まずは空の新規プロジェクトを作ります。
![UE4_VIVEFocus9.png](https://qiita-image-store.s3.amazonaws.com/0/214053/d0484f7b-5089-16a6-96eb-506b9c6c79cc.png)

######プロジェクトを開く前に
プロジェクトが作成できたら、一度UE4エディターを閉じて、サンプルプロジェクト内の「Plugins」フォルダを、今作成したプロジェクト内にコピーします。
![UE4_VIVEFocus11.png](https://qiita-image-store.s3.amazonaws.com/0/214053/eb6a87cc-9ddf-474a-4201-688c20a22f56.png)
![UE4_VIVEFocus12.png](https://qiita-image-store.s3.amazonaws.com/0/214053/55da985d-4a99-ffe3-9815-13f513f44636.png)

そしてサンプルプロジェクト内の「Config」フォルダにある「DefaultInput.ini」も、作成したプロジェクトの「Config」フォルダ内にコピーします。
![UE4_VIVEFocus14.png](https://qiita-image-store.s3.amazonaws.com/0/214053/70fe46b7-efff-9cb7-d226-1b640d8fdafc.png)

コピーできたら、プロジェクトを開きます。
![UE4_VIVEFocus13.png](https://qiita-image-store.s3.amazonaws.com/0/214053/e0ff8773-078d-b153-de24-b9f0e22a0a48.png)

######プロジェクトとプラグインの設定
プロジェクトを開いたらまず「編集」から「プロジェクト設定」を開いて、VIVEFocus用にプロジェクト設定を変更します。

まず「プロジェクト」→「説明」→「Settings」にある「Start in VR」にチェックを入れます。
![UE4_VIVEFocus15.png](https://qiita-image-store.s3.amazonaws.com/0/214053/76a8cb16-1138-8049-06c5-62510931c791.png)

次に「プラットフォーム」→「Android」→「APK Packaging」の「Enable Gradle instead of Ant」にチェックが入っていることを確認します(チェックが入っていない場合はチェックを入れます)。ついでに「Minimum SDK Version」も「25」に設定しておきます。
あと「Package game data inside .apk?」にもチェックを入れておきます。
![UE4_VIVEFocus24.png](https://qiita-image-store.s3.amazonaws.com/0/214053/ad032007-2f98-246a-2381-3bfdf89df388.png)

最後に先ほどのサンプルプロジェクトでも行った、Android開発用の設定も行えていない場合は行っておきます。
(「プロジェクトはAndroidプラットフォームに対応していません」のところで、「今すぐ設定」を押すやつです。)
![UE4_VIVEFocus17.png](https://qiita-image-store.s3.amazonaws.com/0/214053/d37f99e4-6c85-0544-c239-605fa753ba5c.png)

プロジェクト設定はこれで終わりなので、次は「編集」から「Plugins」を開きます。
「Project」→「Virtual Reality」から「WaveVR Plugin」が有効になっていることを確認します(有効になっていなかったら有効にします)。
![UE4_VIVEFocus18.png](https://qiita-image-store.s3.amazonaws.com/0/214053/bcb570f0-0801-389d-3893-f408ac51734c.png)

そして今度はデフォルトで有効になっている他のVR系プラグインを全て無効にします。
「Built-In」→「Virtual Reality」から有効になっているプラグインを全て無効にします。
(デフォルトだと「OculusVR」と「SteamVR」が有効になっていると思いますので、その2つを無効にします。)
この変更を行うと、UE4エディターの再起動を要求されるので、再起動します。
![UE4_VIVEFocus19.png](https://qiita-image-store.s3.amazonaws.com/0/214053/e4cf6e98-0439-b5d4-94aa-51fa2646b82e.png)
![UE4_VIVEFocus20.png](https://qiita-image-store.s3.amazonaws.com/0/214053/ee6d9ff6-eeb2-2bf0-aed0-5bd8b996ce41.png)

これでプロジェクトとプラグインの設定は終わりましたので、実機にデプロイできる状態になりました。
サンプルプロジェクトと同様の手順でデプロイをします。
![UE4_VIVEFocus21.png](https://qiita-image-store.s3.amazonaws.com/0/214053/9f5b8398-b45c-81ae-78d5-4f08d992aeef.png)
![UE4_VIVEFocus22.png](https://qiita-image-store.s3.amazonaws.com/0/214053/7d013496-4b97-c0e5-aa8c-324ecdd37843.png)
![UE4_VIVEFocus23.png](https://qiita-image-store.s3.amazonaws.com/0/214053/f63f12e0-333d-8fa8-dcd6-cc18c9bca3f8.png)

プロジェクトがStarterContent入ったもので作成したため、あのイスの画面が見れます。
あと、特別な設定はなくともVRのHMDトラッキングはできるため、この時点で平行移動もできます。
![Screenshot_20181210-225912.png](https://qiita-image-store.s3.amazonaws.com/0/214053/f63e54ee-6fd7-3474-2f0f-97e8ce25148f.png)
![Screenshot_20181210-225927.png](https://qiita-image-store.s3.amazonaws.com/0/214053/16e44ee8-8857-3d5c-10e5-c7ff12675755.png)

####サンプルプロジェクトの注意点
プラグイン内の一部BPで「DefaultInput.ini」に設定されているActionMappingが使用されているため、この手順のようにその辺りも一緒に移行してこないと、プラグイン内の一部BPで警告がでます。
また、Pluginの「Plugins\WaveVR\Content\Materials\ControllerModel\Generic」にある「FbxScene_Generic_3Dof_Controller_MultipleComponent.uasset」がUE4エディター上での読み込みに失敗します(パッケージ化する際に警告がでるかと思います)。これはまだ原因とか調べられてないので、よく解りませんが、ひとまずパッケージ化して動かすことはできますので、今回は保留しておきます。

##コントローラーやHMDとのやり取り
####HMDのトラッキングについて
何もしなくてもひとまずHMDのトラッキングはしてますが、初期化(原点設定)はした方がいい感じなので、それをやっておきます。
まず、Pawnを親クラスとしてブループリントを作成します。
![UE4_VIVEFocus25.png](https://qiita-image-store.s3.amazonaws.com/0/214053/6d41ad3e-247e-365a-f92b-827c4f8db1ad.png)
![UE4_VIVEFocus26.png](https://qiita-image-store.s3.amazonaws.com/0/214053/4a593ea9-708e-8a1a-2703-7aa4ec810237.png)
![UE4_VIVEFocus27.png](https://qiita-image-store.s3.amazonaws.com/0/214053/fa667d67-089a-5b1d-cdb0-f001391a9e3b.png)

ブループリントを作成したら、まずVR用のカメラのルート用のSceneコンポーネントを追加します。
そして、その子の要素として、Cameraコンポーネントを追加します。
![UE4_VIVEFocus28.png](https://qiita-image-store.s3.amazonaws.com/0/214053/cc5037b6-9ca7-d7ca-e987-2a3ab0faca6a.png)

次にイベントグラフでノードを追加していきます。
「BeginPlay」ノードにつなぐ形で「Set Tracking Origin」ノードを追加します。引数の「Origin」はひとまず座位想定で「Eye Level」を設定しておきます。
![UE4_VIVEFocus29.png](https://qiita-image-store.s3.amazonaws.com/0/214053/3fadfc32-0112-1488-3427-1babeb91ea50.png)
![UE4_VIVEFocus30.png](https://qiita-image-store.s3.amazonaws.com/0/214053/b2f72607-0489-e623-d28c-4dc5946edd2b.png)

視点位置のオフセットとして、カメラのルート用に追加したSceneコンポーネントのトランスフォームの位置のZ値に180を設定します。
これで原点設定はできました。
![UE4_VIVEFocus31.png](https://qiita-image-store.s3.amazonaws.com/0/214053/69bb54d8-fc7e-b4b4-6fa5-5292e046da5c.png)

####コントローラーのトラッキングについて
UE4でモーションコントローラーをトラッキングする際はMotionControllerコンポーネントを使う方式が一般的ですが、
現状のWaveVRプラグインでは対応していないようで、現在のコントローラーの状態を取得する関数をTick等で呼び、VR空間内のコントローラー状態を更新する必要があるようです。

先ほどHMDのトラッキングの際に作成したブループリントに仮想のコントローラーをつけて試していきます。
StaticMeshコンポーネントを追加します。
StaticMeshには「Plugins\WaveVR\Content\Materials\ControllerModel\Generic」にある「Unreal___CM__Body」をひとまず設定しておきます。
![UE4_VIVEFocus35.png](https://qiita-image-store.s3.amazonaws.com/0/214053/945c67c9-6711-ab27-f703-6f4da821008f.png)

追加できたら、Tickにて状態を更新するようにします。
「GetWaveVRInputControllerOrientation」ノードを追加し、モーションコントローラーの回転状態を取れるようにします(引数のDeviceには、ひとまず右手用にDevice Type Controller Rightを設定しておきます)。
そしてその回転状態をモーションコントローラー用のStaticMeshに反映していきます。
StaticMeshから「SetRelativeRotation」ノードを呼び、「New Rotation」に「GetWaveVRInputControllerOrientation」の戻り値「Rotation Value」を設定します。
![UE4_VIVEFocus44.png](https://qiita-image-store.s3.amazonaws.com/0/214053/40be9346-2beb-722c-32c5-dd1126ab44e7.png)

####コントローラーの入力について
基本的にはHTCVIVE等のVR系の入力と同じような感じで管理できるようになっていました。
ActionMappingとして色々登録されているので、それを使うのが判りやすそうです。
![UE4_VIVEFocus42.png](https://qiita-image-store.s3.amazonaws.com/0/214053/5b20fa7c-c612-8841-fbb3-564b2d29c6a7.png)

今回はテスト的にボタン押下でデバッグ用の文字列を出力して確認します。
先ほど作ったブループリントのイベントグラフ内に「インプットアクションDPadUp_Right」ノードを追加します(実機のコントローラーのパッドの部分の上部の入力用です)。
そして、押された時に適当なメッセージをPrintStringノードで表示させるようにします。
![UE4_VIVEFocus43.png](https://qiita-image-store.s3.amazonaws.com/0/214053/eec8b50d-8c0f-7f08-5228-53080d58a112.png)

あとはデプロイ時に今作ったPawnをデフォルトでSpawnされるように設定しておきます。GameMode作って、DefaultPawnに今作ったPawnを設定して、そのGameModeがデフォルトで使われるようにします(VIVEFocus無関係なUE4の部分なので、省略します)。

これでデプロイするとこんな感じで、なんとなくコントローラーの向きだったり、入力だったりを取れます(コントローラー関連だとController Loaderとかもありますが、長くなっていくので今回はなしです)。
![Screenshot_20181211-022624.png](https://qiita-image-store.s3.amazonaws.com/0/214053/a32ea2b9-4265-1558-2916-08cb0545d531.png)
![Screenshot_20181211-022815.png](https://qiita-image-store.s3.amazonaws.com/0/214053/2c85fce9-516e-0ba1-c87f-f383742f53c7.png)

####フロントカメラについて
たぶん後で追記します。

##さいごに
基本SDKの公式ドキュメントベースですが、ちょっと足りないところがあった感じだったので、こういった形で最低限をまとめ直した形で、諸々の手順を記載しました。
実際Pluginの導入部分だけでも色々とまだ開発途中という状態を感じられたかとは思いますし、WaveVRプラットフォーム自体、日本ではDaydream以上にマイナー感がありますが、
VIVEFocusのハード自体はスライドにも記載したようにすごくいい点があるので、選択肢の1つとして考えられたらと思います(VIVEFocus自体がまだ開発者向けの販売というのはありますが)。

せっかく最初からビデオシースルー使えるスタンドアロンVRHMDなので、それ系も何か作れたらいいな。

---
明日は12日目、@FumiyaShibusawaさんです。