この記事を手に取っていただき、ありがとうございます。
なんちゃってエンジニア Mojatto です。
この記事について
この記事は、Unreal Engine (UE) Advent Calendar 2023 にエントリーしています。
レベルを問わず、Unreal Engine (UE) + Unreal Engine for Fornite (UEFN) に関する情報共有を目的とした記事が多く投稿されていますので、是非他の投稿もチェックしてみてください。
概要
スタンドアロン型VRHMD「MetaQuest3」の登場により、SNS上では空間マッピングやパススルー機能を用いたMRアプリの事例が多く発表されています。
かくいう私も、少し前に同じMeta社のVRHMD「MetaQuestPro」を用いてパススルー機能を試したりしていたこともありましたが・・・
(この時は Unityソフトウェア + MRTK3 で試してました)
今回はあえて別ブランドのデバイスで、かつUnrealEngine5を用いてパススルー機能を動かす簡単なアプリを作ってみようと思います。
要件
作るもの
任意の3Dオブジェクトをシーン上に配置し、HMDデバイスのパススルー機能を使ってUnrealEngine側で描画しているオブジェクトと現実の映像を合成して見ることができるのみの、簡易的なMRもどきアプリを作ってみます。
使用するデバイス
2023年2月に国内で発売され、睡眠VRに最適なHMDデバイスとして話題となった、HTC社のモジュラー型HMD「HTC VIVE XR Elite」を使用します。
ゴーグル部とバッテリー部が分離可能で、時と場合に応じてデバイスの形態を切り替えられる点が特徴のデバイスです。
デバイス事態に興味を持たれた方は、既に大手メディアからレビュー記事が多数出ていますので、ぜひチェックしてみてください。
検証環境
- 開発PC
- Windows11 PC (GPD WIN MINI)
- CPU : AMD Ryzen 7 7840U
- RAM : 32 [GB]
- GPU : AMD Radeon 780M (iGPU)
- Windows11 PC (GPD WIN MINI)
- 使用UnrealEngineバージョン
- UnrealEngine 5.1.1
作業手順
事前準備
以下のものや環境が必要です。
- UnrealEngine5.1が導入済みでAndroid向けにビルドできる環境
※ 未整備の場合、公式ドキュメントや有志の記事を参考に環境整備を行ってください。
※ VIVE XR Elite 向けの環境構築メモもあります。良ければこちらもぜひ!
- HTC VIVE XR Elite 本体 (VIVE Focus 3をお持ちの方も本記事の実装方法が使えます)
- VIVE OpenXR Unreal Plugin
HTC ViveブランドHMDの専用機能を使えるようにするためのOpenXRプラグインです。
本記事ではUnrealEngine5.1で検証しておりますので、本記事の条件と合わせて試される場合は、下記URLの公式ページより、UE5.1向けのプラグインをダウンロードしてください。
- 表示したいもの (任意。3Dオブジェクトなら何でもよい)
パススルー機能を利用した状態で、眺めたい3Dオブジェクトを用意すると、よりパススルーをしている感覚が得られるかと思います。
エディタからすぐ出せるCubeでも良し、グレイマンでも良し。ぜひ用意してみてください。
この記事では、QuQu様のVRChat向けアバター「New NecoMaid」に付属されているVRMモデルを使用します。
- 表示したいものに必要なインポータープラグイン (任意)
VRMモデルなど、UnrealEngineで標準に扱えないファイル形式の3Dオブジェクトを使用したい場合は、インポートに必要なプラグインを別途用意し、プロジェクトに導入してください。
VRMモデルをインポートしたい場合は、はるべえ様の「VRM4U」を導入するのがおすすめです。
手順
手順としては、大まかに以下のような流れとなります。
- 「バーチャルリアリティ」テンプレートでプロジェクトを新規作成する
- VIVE OpenXR Unreal Plugin をプロジェクトに導入する
- VIVE XR Elite 向けにプロジェクト設定を変更する
- コントローラ入力のマッピング設定を追加する
- パススルー用天球オブジェクトを作成する
- パススルー切り替え処理を実装する
- 眺めたい3Dオブジェクトをシーン上に配置する
- VIVE XR Elite 向けにプロジェクトをパッケージングする
1.「バーチャルリアリティ」テンプレートでプロジェクトを新規作成する
新規にプロジェクトを作成します。
慣れている方は空のプロジェクトから始めてもよいですが、セットアップ済みのVRPawnやVR向けにプロジェクト設定がある程度変更されている「バーチャルリアリティ」テンプレートを使用するのが良いでしょう。
2.VIVE OpenXR Unreal Plugin をプロジェクトに導入する
作成したプロジェクトに、VIVE OpenXR Unreal Plugin を導入します。
公式サイトからプラグインをダウンロードすると、ローカルに以下のような名称のZipファイルが保存されているかと思います。
vive_openxr_plugin_<バージョン番号>.zip
こちらを展開すると、ViveOpenXR
というフォルダが生成されます。このフォルダを、作成したプロジェクトのディレクトリ直下にあるPlugins
フォルダ配下に配置します。Plugins
フォルダがない場合は、新規に作成してからViveOpenXR
フォルダを配置してください。
作成したプロジェクトを開き、Unrealエディタが起動したら、メニューバーから「編集 > プラグイン」を選択してプラグイン管理ウィンドウを表示します。正しくプラグインが導入されていれば、「インストール済み > Virtual Reality」欄に「Vive OpenXR」という項目が現れます。項目の左側にあるチェックボックスにマークを付け、プロジェクトを開きなおすことで、プラグインが有効化されます。
3.VIVE XR Elite 向けにプロジェクト設定を変更する
プロジェクト設定を開き、プロジェクト設定ウィンドウ左側のリストから「プラグイン > Vive OpenXR」を選択します。ウィンドウ右側の項目を確認し、以下の項目にチェックマークがついていることを確認します。チェックマークがついていないものは、項目右側にあるチェックボックスをクリックし、チェックマークを付けてください。
- コントローラ
- Enable Focus3 Controler
- Passthrough
- Enable Passthrough
4.コントローラ入力のマッピング設定を追加する
パススルー切り替え用にコントローラボタンのマッピング設定を追加します。
従来通りプロジェクト設定からアクションマッピング設定を追加する方法でもよいですが、本記事ではUE5.1から推奨となった「EnhancedInput」を使用して設定してみます。
コンテンツブラウザーから任意の場所に「入力マッピング」アセットを作成し、
ダブルクリックで編集画面を開き内容を以下のように編集します。
次にコンテンツブラウザーから任意の場所に「入力マッピングコンテキスト」「プレイヤーマッピング可能入力コンフィグ」アセットを作成し、
それぞれ以下のように内容を編集します。
- 入力マッピングコンテキストアセット
- プレイヤーマッピング入力可能コンフィグアセット
最後にプロジェクト設定を開いてプロジェクト設定ウィンドウ左側のリストから「プラグイン > OpenXR入力」を選択し、ウィンドウ右側の「EnhancedInput > Mappable Input Config for XR」に、作成したプレイヤーマッピング入力可能コンフィグアセットを指定します。
EnhancedInputについて詳しく知りたい方は、ポジTA様のZennコンテンツ「Unreal Engine 5から始める C++ & Blueprint」にあるChapter70の内容がわかりやすいかと思いますので、チェックしてみてください。本来は有償のコンテンツですが、本記事執筆時点では各Chapterを無償で公開してくださっています。
5.パススルー用天球オブジェクトを作成する
パススルー用の天球オブジェクトを作成します。
まずはパススルー表現用にマテリアルを2つ作成します。コンテンツブラウザーから任意の場所に、以下のような名称のマテリアルを作成します。
- M_UnderlayClearAlpha
- M_UnderlayClearColor
次にマテリアルエディタを開き、マテリアルの結果ノードを選択したうえで、詳細タブからそれぞれ画像のようにパラメータを変更します。
- M_UnderlayClearAlpha
- マテリアル
- 「BlendMode」を「Translucent」に変更
- 「ShadingModel」を「Unlit」に変更
- 透過処理 > 詳細設定
- 「White Only Alpha」のチェックボックスをオフにする
- マテリアル
- M_UnderlayClearColor
- 「BlendMode」を「Masked」に変更
- 「ShadingModel」を「Unlit」に変更
マテリアルを作成したら、パススルー用天球オブジェクトを作成するためのActorBPクラスを作成し、コンポーネントタブにて以下のようにスタティックメッシュコンポーネントを2つ追加します。
追加したスタティックメッシュコンポーネントに対し、それぞれ以下のようにスタティックメッシュアセットとマテリアルを指定します。スタティックメッシュアセットは、エンジンコンテンツにある「SM_SkySphere」を使用します。
- UnderlayClearAlpha
- UnderlayClearColor
6.パススルー切り替え処理を実装する
前項で作成したActorBPクラスに対し、パススルー切り替え処理を実装します。
まず、以下の2つの関数と1つの変数を追加します。
- 関数
- StartPassthrough・・・パススルーを有効化する関数
- StopPassthrough・・・パススルーを無効化する関数
- 変数
- usePassthrough・・・パススルーを使用しているかを示すboolean型変数
次に作成した関数に処理を実装していきます。
StartPassthrough関数には、以下のようにノードネットワークを組みます。
Pure関数「IsPassthroughEnabled」は、実行環境でViveOpenXRによるパススルー機能が利用可能であるかをboolean型で返すものです。エディタ上ではFalseが返されます。
関数「CreatePassthroughUnderlay」は、描画レイヤーの最背面にパススルー映像を投影するオブジェクトを生成します。引数「InPassthroughLayerForm」には、パススルー映像の投影方法を指定することができ、「Planar (全画面に対して投影)」「Projected (一部領域のみを任意のメッシュに投影)」のいずれかを選択できます。本記事では単純にパススルー映像を投影したいので、「Planar」を指定します。この関数は、正常にパススルー映像を投影できたかをboolean型の返り値として出力します。この出力を、パススルー機能を有効化しているかどうかの判定として、usePassthrough変数に設定します。
次に、StopPassthrough関数に以下のようなノードネットワークを組みます。
まず、Pure関数「IsPassthroughEnabled」の出力をチェックし、パススルー機能が利用可能である場合のみ以降の処理をするよう分岐させます。
次に、関数「DestroyPassthroughUnderlay」でパススルー映像を投影するオブジェクトを破棄します。この関数は、正常にパススルー映像を破棄できたかをboolean型の返り値として出力します。正常にパススルー映像が破棄されたらtrueを返すため、この出力をNOTノードで反転したうえで、usePassthrough変数に設定します。
最後にActorBPクラスのイベントグラフを開き、全体の処理を実装していきます。
BeginPlayイベントノードを配置し、右クリックメニューから関数「AddMappingContext」を追加してExecピンへ接続します。この関数は、引数「MappingContext」に指定した入力マッピングコンテキストを、引数「Target」に指定したPlayerControllerから利用可能にする処理を実行します。引数「MappingContext」には、「4.コントローラ入力のマッピング設定を追加する」で作成した入力マッピングコンテキストを指定します。
次に、右クリックメニューから入力イベント「EnhancedInputAction IA_Keys_APress_R」を追加し、以下の画像のようにノードネットワークを組みます。
usePassthroughの値に応じて分岐し、trueであれば関数「StopPassthrough」を、falseであれば関数「StartPassthrough」をコールし、パススルー機能の有効状態切り替えを行います。そののち、usePassthroughの値に応じて、パススルー映像投影用の天球オブジェクト「UnderlayClearAlpha」「UnderlayClearColor」の可視化状態を、関数「SetVisiblity」を用いて切り替えます。
7.眺めたい3Dオブジェクトをシーン上に配置する
コンテンツブラウザーから任意の場所に空のレベルアセットを作成してダブルクリックで開き、前項で作成したパススルー用天球オブジェクトを作成するためのActorBPクラスと最低限のライトを配置します。
次に、HMDの動きをカメラに反映させるために、「バーチャルリアリティ」テンプレートに含まれるPawnクラス「VRPawn」を配置します。このBPクラスは、デフォルトでは「Content > VRTemplate > Blueprints」に配置されています。
最後に、眺めたい3Dオブジェクトがあれば、データをインポートの上、VRPawnの正面に配置します。
この時、カメラから離れすぎていると、ルームセットアップによっては想定より遠い位置に配置されてしまうため、できるだけ近い位置に配置したほうが良いです。
8.VIVE XR Elite 向けにプロジェクトをパッケージング・デプロイする
ここまで作業が完了したら、いよいよ VIVE XR Elite 実機にプロジェクトをパッケージング・デプロイしていきます。
VIVE XR Elite本体をPCに接続し、エディタウィンドウ上部にある「プラットフォーム」ボタンを押し、ドロップダウンリストから「クイック起動 > All_Android_On_<PC名> > VIVE XR Series」の順に項目を選択します。
すると、プロジェクトのパッケージング作業が開始され、アウトプットログが高速で流れ始めます。
特に初回のパッケージングはかなり時間がかかりますので、無事にパッケージングできることを祈りつつ、コーヒーでも飲みながら待ちましょう。
右下のポップアップメッセージが以下のように表示されれば、無事にパッケージングが完了し実機上でアプリが実行されています。
動作確認
実機で動作させてみたサンプルです。
右側のコントローラのボタンを押すと、パススルーの表示状態が切り替わり、自身が移動することでその方向から3Dオブジェクトを眺めることができていることがわかります。
視点の動きに伴って3Dオブジェクトが遅れて追従しているタイミングがありますが、これは6DoFのトラッキング精度によるものと思われます。
あとがき
本記事では、UnrealEngineを用いてVIVE XR Elite向けにパススルー機能を試すための簡単なアプリを作ってみました。
正直なところ、MetaのSDKと異なりゴリゴリC++で実装することになるのではという先入観があったので身構えていたところがありましたが、Blueprintのみで簡単に機能を利用することができました。
ViveOpenXRプラグインでは、ハンドトラッキング・インタラクションをはじめとして、VIVE XR Elite向けに利用できる機能がいろいろあるようなので、またの機会に試してみようと思います。
コメント